/*
 *************************************************************************
 * The contents of this file are subject to the Openbravo  Public  License
 * Version  1.0  (the  "License"),  being   the  Mozilla   Public  License
 * Version 1.1  with a permitted attribution clause; you may not  use this
 * file except in compliance with the License. You  may  obtain  a copy of
 * the License at http://www.openbravo.com/legal/license.html 
 * Software distributed under the License  is  distributed  on  an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific  language  governing  rights  and  limitations
 * under the License. 
 * The Original Code is Openbravo ERP. 
 * The Initial Developer of the Original Code is Openbravo SL 
 * All portions are Copyright (C) 2001-2006 Openbravo SL 
 * All Rights Reserved. 
 * Contributor(s):  ______________________________________.
 ************************************************************************
*/
<!--
var baseFrameServlet = "http://localhost:8880/openbravo/security/Login_FS.html";
var gColorSelected = "#c0c0c0";
var gWhiteColor = "#F2EEEE";
var arrGeneralChange=new Array();
var dateFormat;
var defaultDateFormat = "%d-%m-%Y";

//Array de los números de días de cada mes
daysOfMonth = new Array( 
new Array(0,31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31), //No bisiestos
new Array (0,31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) //Bisiestos
);

/**
* Esta librería JavaScript contiene las funciones y procedimientos básicos que se utilizan en
* todas las páginas html. Son elementos básicos como el posicionamiento del foco en un control
* de la página, control de campos numéricos...
*/

var gBotonPorDefecto;
var gEnviado=false;
var arrTeclas=null;
var gAUXILIAR=0;
var gWaitingCallOut=false;

/** 
* @name focoPrimerControl
* @format function focoPrimerControl(Formulario, Campo)
* @comment Posiciona el cursor en el primer campo visible de un formulario
*
* @param <b>Formulario</b> - Es un parámetro que puede no existir, pero que indica cúal es el formulario
*           donde se encuentra el campo sobre el que queremos posicionar el cursor. En
*           caso de no existir este parámetro, se toma el primer formulario de la página. <BR>
*        <b>Campo</b> - Nombre del control en el que se quiere posicionar el foco
* @example focoPrimerControl();
*/
function focoPrimerControl(Formulario, Campo)
{
  var encontrado = false;
  if (Formulario==null) Formulario=document.forms[0];
  var total = Formulario.length;
  for(var i=0;i<total; i++)
  {
    if ((Formulario.elements[i].type != "hidden") && (Formulario.elements[i].type != "button") && (Formulario.elements[i].type != "submit") && (Formulario.elements[i].type != "image") && (Formulario.elements[i].type != "reset")) 
    { 
      if(Campo!=null) {
        if (Campo == Formulario.elements[i].name && !Formulario.elements[i].readonly && !Formulario.elements[i].disabled) {
          Formulario.elements[i].focus();
          encontrado=true;
          break;
        }
      } else if (!Formulario.elements[i].readonly && !Formulario.elements[i].disabled) {
        try {
          Formulario.elements[i].focus();
          encontrado=true;
          break;
        } catch (ignore) {}
      }
    }
  }
  if (encontrado && Formulario.elements[i].type && Formulario.elements[i].type.indexOf("select")==-1)
    Formulario.elements[i].select();
}

/** 
* @name limpiar
* @format function limpiar(Formulario)
* @comment Borra el contenido de los campos de texto de un formulario
*
* @param <b>Formulario</b> - Toma el valor del formulario donde están los campos que queremos limpiar
*             y si no existe, toma el primer formulario de la página
* @example limpiar();
*/
function limpiar(Formulario)
{
  if (Formulario == null)
    Formulario = document.forms[0];

  var total = Formulario.length;
  for (var i=0;i<total;i++){
    if (Formulario.elements[i].type == "text" || Formulario.elements[i].type == "password")
      Formulario.elements[i].value = "";
  }
}

/**
* @name confirmar
* @format function confirmar(Accion)
* @comment Es la encargada de presentar un mensaje o no, dependiendo de la <b>Accion<b> que se le
*          pase. Esta función es utilizada por las funciones que realizan envíos de formularios.
* @param <b>Accion</b> - es un texto que indentifica el <b>Command</b> que se ejecuta.
* @return <b>true</b> - en caso de no tener mensaje asociado a dicho <b>Command</b>, o si el usuario
*          ha confirmado el mensaje presentado.<BR>
*         <b>false</b> - si el usuario no confirma el mensaje presentado.
*/
function confirmar(accion)
{
  switch (accion)
  {
  case 'DELETE': return mensaje(2);
  case 'DELETE_RELATION': return mensaje(2);
  case 'GUARDAR': return mensaje(3);
  default: return true;
  }
}

function submitFormGetParams(Command, action) {
  var frm = document.forms[0];
  frm.action=action + "?Command=" + Command;
  var params="";
  for (var i=2;arguments[i]!=null;i++) {
    params += "&" + arguments[i] + ((arguments[i+1]!=null)?("=" + arguments[i+1]):"");
    i++;
  }
  if (params!="") frm.action += params;
  frm.target="_self";
  frm.submit();
  return true;
}

/** 
* @name getParamsScript
* @format function getParamsScript(Formulario)
* @comment Esta función recibe un Formulario en el que existen campos que se quieren enviar y, ella se encarga
*          de capturar todos los campos del formulario con sus valores y transformarlos en una cadena de
*          parámetros de un método GET para poderlos enviar.
*
* @param <b>Formulario</b> - Es el objeto formulario que se quiere enviar. Este parámetro es obligatorio.
* @example getParamScript(document.forms[0]);
*/
function getParamsScript(Formulario) {
  if (Formulario==null) return "";
  var script="";
  var total = Formulario.length;
  for (var i=0;i<total;i++) {
    if (Formulario.elements[i].type && (Formulario.elements[i].type != "button") && (Formulario.elements[i].type != "submit") && (Formulario.elements[i].type != "image") && (Formulario.elements[i].type != "reset") && (Formulario.elements[i].readonly!="true") && (Formulario.elements[i].name != "Command") && (Formulario.elements[i].name!="") && !Formulario.elements[i].disabled) {
      if (Formulario.elements[i].type.toUpperCase().indexOf("SELECT")!=-1 && Formulario.elements[i].selectedIndex!=-1) {
        script += ((script=="")?"":"&") + Formulario.elements[i].name + "=" + escape(Formulario.elements[i].options[Formulario.elements[i].selectedIndex].value);
      } else if (Formulario.elements[i].type.toUpperCase().indexOf("CHECKBOX")!=-1 || Formulario.elements[i].type.toUpperCase().indexOf("RADIO")!=-1) {
        if (radioValue(Formulario.elements[i]) != null) script += ((script=="")?"":"&") + Formulario.elements[i].name + "=" + escape(radioValue(Formulario.elements[i]));
      } else if (Formulario.elements[i].value!=null && Formulario.elements[i].value!="") {
        script += ((script=="")?"":"&") + Formulario.elements[i].name + "=" + escape(Formulario.elements[i].value);
      }
    }
  }
  return script;
}


/**
* @name submitForm
* @format function submitForm(Campo, Valor, Formulario, Comprobar)
* @comment Esta función envía un formulario poniendo un valor que se le pasa en un campo que se 
*          le indica antes de enviarlo y pudiendo comprobar si ya se había llamado a esta función
*          sin haber podido obtener un resultado todavía, es decir, comprobando que si se está 
*          enviando todavía no permita volver a enviar hasta que no se realice el primer envío.
*
* @param <b>Campo</b> - Un objeto que referencia al campo en el que queremos depositar un valor que
*         le pasamos a continuación. <BR>
*        <b>Valor</b> - Un string que indica el valor que queremos dejar en el campo que le hemos
*         indicado antes. <BR>
*        <b>Formulario</b> - Un objeto que referencia al formulario que queremos enviar. Si este
*         parámetro se deja a null se entiende que es el formulario primero de la página. <BR>
*        <b>Comprobar</b> - Booleano que indica si queremos que controle si ya se está enviando 
*         este formulario, no realizando varios envíos a la vez. El valor de este parámetro, 
*         por defecto, es false
*
* @return <b>true</b> - si todo va bien y los datos son enviados correctamente.<BR>
*         <b>false</b> - si hay algún problema y los datos no se pueden enviar.
* @example submitForm(document.forms[0].inpCampo, "FIND", null, true);
*/
function submitForm(campo, valor, Formulario, bolComprobar, isCallOut) {
  if (Formulario == null) Formulario = document.forms[0];
  if (isCallOut==null) isCallOut = false;
  if (bolComprobar!=null && bolComprobar) {
    if (gEnviado==1) {
      mensaje(16);
      return false;
    } else {
      gEnviado=1;
      if (isCallOut) gWaitingCallOut=true;
      campo.value = valor;
      Formulario.submit();
    }
  } else {
    if (isCallOut) gWaitingCallOut=true;
    campo.value = valor;
    Formulario.submit();
  }
  return true;
}

/**
* @name reloadFunction
* @format function reloadFunction(text)
* @comment Esta función se encarga de retrasar la ejecución del comando que se le pasa por parámetro, 
*          el cual será llamado al pasar un tiempo determinado. Se utiliza para simular un timer en
*          javascript.
*
* @param <b>text</b> - Es una cadena de texto que contiene un comando javascript.
*
* @return <b>ID</b> - Devuelve el identificador del timer para poder cancelarlo en cualquier momento.
* @example reloadFunction("alert('prueba');");
*/
function reloadFunction(text) {
  return setTimeout(text, 1000);
}

/**
* @name setChangedField
* @format function setChangedField(campo, Formulario)
* @comment Se encarga de marcar cuál ha sido el último campo cambiado para depurar si en una pantalla, 
*          se han producido cambios. Requiere la existencia de un campo llamado inpLastFieldChanged.
*
* @param <b>campo</b> - Es un objeto que contiene el campo que ha sido modificado. Normalmente colocaremos
*                       esta función en el onChange del propio campo modificado, por lo que en este parámetro
*                       pasaremos el objeto this.<BR>
*        <b>Formulario</b> - Es el formulario en el que se encuentra el campo inpLastFieldChanged. Si se 
*                            encuentra en el formulario principal de la ventana, no es necesario indicarlo.
*
* @return <b>true</b> - Si todo va bien.<BR>
*         <b>false</b> - Si no encuentra el campo inpLastFieldChanged.
* @example onChange="setChangedField(this);return true;"
*/
function setChangedField(campo, Formulario) {
  if (Formulario==null || !Formulario) Formulario = document.forms[0];
  if (Formulario.inpLastFieldChanged==null) return false;
  Formulario.inpLastFieldChanged.value = campo.name;
  return true;
}

/**
* @name checkForChanges
* @format function checkForChanges(Formulario)
* @comment Esta función comprueba si se han producido cambios en el formulario que se le indique.
*          Es necesario que exista un campo llamado inpLastFieldChanged, ya que es sobre este campo
*          sobre el que comprueba si existen modificaciones. Esta función es complemento de la función 
*          setChangedField.
*
* @param <b>Formulario</b> - Es el formulario en el que se encuentra el campo inpLastFieldChanged. Si se 
*                            encuentra en el formulario principal de la ventana, no es necesario indicarlo.
*
* @return <b>true</b> - Si el campo inpLastFieldChanged contiene algún dato y se pulsa OK en el mensaje emergente.<BR>
*         <b>false</b> - Si no contiene ningún dato o se pulsa CANCEL en el mensaje emergente.
* @example checkForChanges();
*/
function checkForChanges(Formulario) {
  if (Formulario==null) Formulario = document.forms[0];
  if (inputValue(Formulario.inpLastFieldChanged)!="") {
    if (!mensaje(10)) return false;
  }
  return true;
}


function sendDirectLink(Formulario, columnName, parentKey, url, keyId, tableId, newTarget, bolComprobarCambios) {
  if (Formulario == null) Formulario = document.forms[0];
  var frmDepuracion = document.forms[0];
  var accion = "DEFAULT";
  if (bolComprobarCambios==null) bolComprobarCambios = false;
  if (arrGeneralChange!=null && arrGeneralChange.length>0 && bolComprobarCambios) {
    var strFunction = "sendDirectLink('" + Formulario.name + "', '" + columnName + "', '" + parentKey + "', '" + url + "', '" + keyId + "', '" + tableId + "', " + ((newTarget==null)?"null":"'" + newTarget + "'") + ", " + bolComprobarCambios + ")";
    reloadFunction(strFunction);
    return false;
  }
  if (bolComprobarCambios && !checkForChanges(frmDepuracion)) return false;
  if (confirmar(accion)) {
    Formulario.action = url;
    if (newTarget != null) Formulario.target = newTarget;
    Formulario.inpKeyReferenceColumnName.value = columnName;
    Formulario.inpSecondKey.value = parentKey;
    Formulario.inpKeyReferenceId.value = keyId;
    Formulario.inpTableReferenceId.value = tableId;
    submitForm(Formulario.Command, accion, Formulario, false, false);
  }
  return true;
}

function dispatchEventChange(target) {
  if (!target) return true;
  if (!target.type) return true;
  if (target.onchange && target.defaultValue && target.defaultValue != inputValue(target)) target.onchange();
  else if (target.onblur) target.onblur();
  return true;
}

/**
* @name submitCommandForm
* @format function submitCommandForm(Command, Depurar, Formulario, newAction, newTarget, Comprobar, ComprobarCambios, isCallOut)
* @comment Esta es la función que principalmente se utilizará para implementar las operaciones 
*          a realizar por los botones que pongamos en la página. Su misión es la de enviar un 
*          formulario poniendo el Command (se trata de un texto que utilizamos para indicar al 
*          servlet el tipo de operación que queremos que realice o el botón que le ha llamado) 
*          que indiquemos. Permite hacer una depuración previa, pudiendo cancelar el envío si la
*          depuración no es satisfactoria.<BR><BR>
*
*          La ejecución de esta función requiere que en el formulario a enviar exista un campo 
*          oculto que se llame <b>Command</b>, el cual lo utilizará esta función para enviar el 
*          Command que le indiquemos.
*
* @param <b>Command</b> - Texto que permite al servlet identificar que tipo de operación debe 
*          realizar o qué botón le ha llamado. <BR>
*        <b>Depurar</b> - Booleano que indica si se quiere realizar una depuración antes de enviar
*          el formulario. El valor de este campo, por defecto, es false. Si esta opción se pone a 
*          true, se deberá implementar una función en la propia página que se llame <b>depurar</b> 
*          y en la que realizaremos las depuraciones pertinentes, devolviendo true o false 
*          obligatoriamente. Si devolvemos false no se enviará el formulario. Esta función recibe 
*          como parámetro el <b>Command</b>. <BR>
*        <b>Formulario</b> - Un objeto que referencia al formulario que queremos enviar. Si este 
*          dato se pone null, se entiende que se trata del primer formulario de la página. <BR>
*        <b>newAction</b> - Un string que indica la URL de la página a la que queremos enviar el
*          formulario. Si se deja a null no se cambia la URL que tenga establecido el formulario 
*          en su propiedad <b>action</b> <BR>
*        <b>newTarget</b> - Un string que indica un nombre de una ventana o frame al que queremos 
*          enviar el formulario. Se refiere a la propiedad <b>target</b> del formulario. Si esta 
*          opción no se indica o se deja a null, se mantiene la que ponga en el formulario. <BR>
*        <b>Comprobar</b> - Booleano que indica si queremos que controle si ya se ha pulsado este 
*          botón anteriormente y todavía no ha podido contestar el servidor, evitando que un usuario
*          pueda dar varias veces al mismo botón, creyendo que no le ha dado, porque tarda en responder.
*          El valor por defecto de este parámetro es false.<BR>
*        <b>ComprobarCambios</b> - Booleano que indica si queremos que la función compruebe, previamente, 
*          si se han producido cambios de datos en la ventana, presentando en tal caso el mensaje emergente
*          correspondiente.<BR>
*        <b>isCallOut</b> - Booleano que indica si estamos haciendo una llamada a un callout.
*
* @return <b>true</b> - si todo va correctamente y se envían los datos.<BR>
*         <b>false</b> - si hay algún problema y los datos no se pueden enviar o se cancela el envío al pulsar
*                        CANCEL en el mensaje emergente de aviso de cambios en la ventana.
* @example submitCommandForm("FIND", false, null, null, null, true, null, false);
*/
function submitCommandForm(accion, bolDepurar, Formulario, newAction, newTarget, bolComprobar, bolComprobarCambios, isCallOut, controlEvt, evt)
{
  if (Formulario == null) Formulario = document.forms[0];
  if (bolDepurar!=null && bolDepurar==true) if (!depurar(accion, Formulario, "")) return false;
  if (bolComprobarCambios==null) bolComprobarCambios = false;
  if (isCallOut==null) isCallOut = false;
  if (controlEvt==null) controlEvt = false;
  if (controlEvt) {
    if (!evt) evt = window.event;
    var target = (document.layers) ? evt.target : evt.srcElement;
    dispatchEventChange(target);
  }
  if (gWaitingCallOut || (arrGeneralChange!=null && arrGeneralChange.length>0 && bolComprobarCambios)) {
    var strFunction = "submitCommandForm('" + accion + "', " + bolDepurar + ", " + Formulario.name + ", " + ((newAction!=null)?("'" + newAction + "'"):"null") + ", " + ((newTarget!=null)?("'" + newTarget + "'"):"null") + ", " + bolComprobar + ", " + bolComprobarCambios + ")";
    reloadFunction(strFunction);
    return false;
  }
  if (bolComprobarCambios && !checkForChanges(Formulario)) return false;
  if (confirmar(accion)) {
    if (newAction != null) Formulario.action = newAction;
    if (newTarget != null) Formulario.target = newTarget;
    submitForm(Formulario.Command, accion, Formulario, bolComprobar, isCallOut);
  }
  return true;
}


/**
* @name submitCommandFormParameter
* @format function submitCommandFormParameter(Command, Campo, Valor, Depurar, Formulario, 
*         newAction, newTarget, Comprobar, ComprobarCambios, isCallOut)
* @comment Esta es la función que principalmente se utilizará para implementar las operaciones 
*          a realizar por los botones que pongamos en la página, en los casos en los que queramos 
*          que, además, envíe un parámetro adicional en función del Link que pinche, de forma que 
*          su aplicación práctica sería para ir al detalle de una línea concreta que de una relación, 
*          de forma que deberemos indicar la clave de la línea de la que queremos ver su detalle, 
*          valor que será diferente dependiendo de la línea que elijamos. Su misión es la de enviar
*          un formulario poniendo el Command (se trata de un texto que utilizamos para indicar al
*          servlet el tipo de operación que queremos que realice o el botón que le ha llamado) que 
*          indiquemos y el valor del que antes hablábamos en un campo del formulario, campo que debe 
*          existir y que, por lo general será un campo oculto. Permite hacer una depuración previa, 
*          pudiendo cancelar el envío si la depuración no es satisfactoria.<BR><BR>
*
*          La ejecución de esta función requiere que en el formulario a enviar exista un campo oculto
*          que se llame <b>Command</b>, el cual lo utilizará esta función para enviar el Command que
*          le indiquemos. También deberá existir el campo en el que queremos guardar el valor clave 
*          que identifica la línea.
*
* @param <b>Command</b> - Texto que permite al servlet identificar que tipo de operación debe realizar
*         o qué botón le ha llamado. <BR>
*        <b>Campo</b> - Un objeto que referencia a un campo del formulario en el que queremos que se
*         deposite el valor clave que identifica a la línea. <BR>
*        <b>Valor</b> - El valor de tipo string que es el valor clave que queremos depositar en el 
*         campo anterior. <BR>
*        <b>Depurar</b> - Booleano que indica si se quiere realizar una depuración antes de enviar 
*         el formulario. El valor de este campo, por defecto, es false. Si esta opción se pone a true, 
*         se deberá implementar una función en la propia página que se llame <b>depurar</b> y en la 
*         que realizaremos las depuraciones pertinentes, devolviendo true o false obligatoriamente. 
*         Si devolvemos false no se enviará el formulario. Esta función recibe como parámetro el
*         <b>Command</b>. <BR>
*        <b>Formulario</b> - Un objeto que referencia al formulario que queremos enviar. Si este dato
*         se pone null, se entiende que se trata del primer formulario de la página. <BR>
*        <b>newAction</b> - Un string que indica la URL de la página a la que queremos enviar el 
*         formulario. Si se deja a null no se cambia la URL que tenga establecido el formulario en 
*         su propiedad <b>action</b>. <BR>
*        <b>newTarget</b> - Un string que indica un nombre de una ventana o frame al que queremos 
*         enviar el formulario. Se refiere a la propiedad <b>target</b> del formulario. Si esta opción
*         no se indica o se deja a null, se mantiene la que ponga en el formulario. <BR>
*        <b>Comprobar</b> - Booleano que indica si queremos que controle si ya se ha pulsado este 
*         botón anteriormente y todavía no ha podido contestar el servidor, evitando que un usuario
*         pueda dar varias veces al mismo botón, creyendo que no le ha dado, porque tarda en responder.
*         El valor por defecto de este parámetro es false.<BR>
*        <b>ComprobarCambios</b> - Booleano que indica si queremos que la función compruebe, previamente, 
*          si se han producido cambios de datos en la ventana, presentando en tal caso el mensaje emergente
*          correspondiente.<BR>
*        <b>isCallOut</b> - Booleano que indica si estamos haciendo una llamada a un callout.
*
* @return <b>true</b> - si todo va correctamente y se envían los datos.<BR>
*         <b>false</b> - si hay algún problema y los datos no se pueden enviar o pulsa el boton CANCEL de la 
*                        ventana emergente de comprobación de cambios.
* @example submitCommandFormParameter("FIND", document.forms[0].inpClave, "12", false, null, null, null, true, false);
*/
function submitCommandFormParameter(accion, campo, valor, bolDepurar, Formulario, formAction, newTarget, bolComprobar, bolComprobarCambios, isCallOut, controlEvt, evt) {
  if (Formulario == null) Formulario = document.forms[0];
  if (bolDepurar!=null && bolDepurar==true) if (!depurar(accion, Formulario, valor)) return false;
  if (bolComprobarCambios==null) bolComprobarCambios = false;
  if (isCallOut==null) isCallOut = false;
  if (controlEvt==null) controlEvt = false;
  if (controlEvt) {
    if (!evt) evt = window.event;
    var target = (document.layers) ? evt.target : evt.srcElement;
    dispatchEventChange(target);
  }
  if (gWaitingCallOut || (arrGeneralChange!=null && arrGeneralChange.length>0 && bolComprobarCambios)) {
    var strFunction = "submitCommandFormParameter('" + accion + "', " + campo.form.name + "." + campo.name + ", '" + valor + "', " + bolDepurar + ", " + Formulario.name + ", " + ((formAction!=null)?("'" + formAction + "'"):"null") + ", " + ((newTarget!=null)?("'" + newTarget + "'"):"null") + ", " + bolComprobar + ", " + bolComprobarCambios + ", " + isCallOut + ")";
    reloadFunction(strFunction);
    return false;
  }

  if (bolComprobarCambios && !checkForChanges(Formulario)) return false;

  if (confirmar(accion)) {
    campo.value = valor;
    if (formAction != null) Formulario.action = formAction;
    if (newTarget != null) Formulario.target = newTarget;
    submitForm(Formulario.Command, accion, Formulario, bolComprobar, isCallOut);
  }
  return true;
}


/**
* @name campoNumerico
* @format function campoNumerico(CampoNumerico, Decimales, Negativo)
* @comment Es la función encargada de controlar que los datos introducidos en un campo sean 
*          numéricos, de tal forma que si no lo son, será la propia función la que lance un mensaje 
*          de error y posicione el foco en el control. Se nos va a permiter controlar que el número 
*          que se haya introducido sea un número entero o no, e incluso que sólo sea positivo o no.
*
* @param <b>CampoNumerico</b> - Objeto que referencia el control de la página que queremos depurar.<BR> 
*        <b>Decimales</b> - Booleano que indica si se admiten números decimales o no. <BR>
*        <b>Negativos</b> - Booleano que indica si se admiten números negativos o no. 
* @return <b>true</b> - si el contenido del campo es numérico.<BR>
*         <b>false</b> - si no es numérico o no cumple alguno de los requisitos especificados.
* @example campoNumerico(document.forms[0].inpImporte, true, false);
* @see @link esNumerico , @link esNumero
*/
function campoNumerico(CampoNumerico, bolDecimales, bolNegativo)
{
  if (!esNumero(CampoNumerico.value, bolDecimales, bolNegativo))
  {
    mensaje(4);
    CampoNumerico.focus();
    CampoNumerico.select();
    return false;
  }
  return true;
}


/**
* @name esNumero
* @format function esNumero(ValorNumerico, Decimales, Negativo)
* @comment Recorre el texto pasado, controlando si todos sus elementos son numéricos o no
*
* @param <b>ValorNumerico</b> - String que contiene el número a depurar.<BR> 
*        <b>Decimales</b> - Booleano que indica si se admiten números decimales o no. <BR>
*        <b>Negativos</b> - Booleano que indica si se admiten números negativos o no.
* @return <b>true</b> - si el contenido del campo es numérico.<BR>
*         <b>false</b> - si no es numérico o no cumple alguno de los requisitos especificados.
*/
function esNumero(strValorNumerico, bolDecimales, bolNegativo) {
  var bolComa = false;
  var esNegativo = false;
  var i=0;
  if (strValorNumerico == null || strValorNumerico=="") return true;
  if (strValorNumerico.substring(i, i+1)=="-") {
    if (bolNegativo !=null && bolNegativo) {
      esNegativo = true;
      i++;
    } else {
      return false;
    }
  } else if (strValorNumerico.substring(i, i+1)=="+")
    i++;
  var total = strValorNumerico.length;
  for (i=i;i<total;i++) {
    if (isNaN(strValorNumerico.substring(i,i+1))) {
      if (bolDecimales && strValorNumerico.substring(i,i+1)=="." && !bolComa) 
        bolComa = true;
      else
        return false;
    }
  }
  return true;
}

function getArrayValue(data, name, defaultValue) {
  if (data==null || data.length<=0) return ((defaultValue!=null)?defaultValue:"");
  var total = data.length;
  for (var i=0;i<total;i++) {
    if (data[i][0]==name) return data[i][1];
  }
  return ((defaultValue!=null)?defaultValue:"");
}

function addArrayValue(data, name, value, isUrlParameter) {
  if (isUrlParameter==null) isUrlParameter=false;
  if (data==null || data.length<=0) {
    data = new Array();
    data[0] = new Array(name, value, (isUrlParameter?"true":"false"));
    return data;
  }
  var total = data.length;
  for (var i=0;i<total;i++) {
    if (data[i][0]==name) {
      data[i][1] = value;
      return data;
    }
  }
  data[total] = new Array(name, value, (isUrlParameter?"true":"false"));
  return data;
}

function addUrlParameters(data) {
  if (data==null || data.length<=0) return "";
  var total = data.length;
  var text = "";
  for (var i=0;i<total;i++) {
    if (data[i][2]=="true") text += ((text!=null && text!="")?"&":"") + data[i][0] + "=" + escape(data[i][1]);
  }
  if (text!=null && text!="") text = "?" + text;
  return text;
}

function openNewLink(url, _name, height, width, top, left, checkChanges, target, doSubmit, closeControl, parameters) {
  parameters = addArrayValue(parameters, "location", "1");
  parameters = addArrayValue(parameters, "scrollbars", "1");
  parameters = addArrayValue(parameters, "status", "1");
  parameters = addArrayValue(parameters, "menubar", "1");
  parameters = addArrayValue(parameters, "toolbar", "1");
  parameters = addArrayValue(parameters, "resizable", "1");
  return openPopUp(url, _name, height, width, top, left, checkChanges, target, doSubmit, closeControl, parameters);
}

function openPopUp(url, _name, height, width, top, left, checkChanges, target, doSubmit, closeControl, parameters) {
  var adds = "";
  if (height==null) height = screen.height - 50;
  if (width==null) width = screen.width;
  if (top==null) top = (screen.height - height) / 2;
  if (left==null) left = (screen.width - width) / 2;
  if (checkChanges==null) checkChanges = false;
  if (closeControl==null) closeControl = false;
  if (doSubmit==null) doSubmit = false;
  if (checkChanges && !checkForChanges()) return false;
  if (url!=null && url!="") url += addUrlParameters(parameters);
  if (target!=null && target!="" && target.indexOf("_")!=0) {
    var objFrame = eval("parent." + target);
    objFrame.location.href=url;
    return true;
  }
  adds = "height=" + height + ", width=" + width + ", left=" + left + ", top=" + top;
  if (navigator.appName.indexOf("Netscape")) {
    adds += ", alwaysRaised=" + getArrayValue(parameters, "alwaysRaised", "1");
    adds += ", dependent=" + getArrayValue(parameters, "dependent", "1");
    adds += ", directories=" + getArrayValue(parameters, "directories", "0");
    adds += ", hotkeys=" + getArrayValue(parameters, "hotkeys", "0");
  }
  adds += ", location=" + getArrayValue(parameters, "location", "0");
  adds += ", scrollbars=" + getArrayValue(parameters, "scrollbars", "0");
  adds += ", status=" + getArrayValue(parameters, "status", "1");
  adds += ", menubar=" + getArrayValue(parameters, "menubar", "0");
  adds += ", toolbar=" + getArrayValue(parameters, "toolbar", "0");
  adds += ", resizable=" + getArrayValue(parameters, "resizable", "1");
  if (doSubmit && (getArrayValue(parameters, "debug", false)==true)) {
	  if (!depurar(getArrayValue(parameters, "Command", "DEFAULT"), null, "")) return false;
  }
  var winPopUp = window.open((doSubmit?"":url), _name, adds);
  if (closeControl) window.onunload = function(){winPopUp.close();}
  if (doSubmit) {
    submitCommandForm(getArrayValue(parameters, "Command", "DEFAULT"), (getArrayValue(parameters, "debug", false)==true), null, url, _name, target, checkChanges);
  }
  winPopUp.focus();
  return winPopUp;
}

function abrirNuevoBrowser(url, _name, height, width, top, left) {
  return openNewLink(url, _name, height, width, top, left, null, null, null, true, null);
}

function abrirExcel(url, _name, checkChanges) {
  return openPopUp(url, _name, null, null, null, null, checkChanges, null, null, false, null);
}

function abrirPDF(url, _name, checkChanges) {
  return openPopUp(url, _name, null, null, null, null, checkChanges, null, null, false, null);
}

function abrirPDFFiltered(url, _name, checkChanges) {
  return openPopUp(url, _name, null, null, null, null, checkChanges, null, true, false, null);
}

function abrirPopUp(url, _name, height, width, closeControl, showstatus) {
  if (height==null) height = 250;
  if (width==null) width = 230;
  return openPopUp(url, _name, height, width, null, null, null, null, null, closeControl, null);
}

function abrirPDFSession(strPagina, strDirectPrinting, strHiddenKey, strHiddenValue, bolComprobarCambios) {
  var direct = (strDirectPrinting!="")?"Y":"N";
  return submitCommandForm("DEFAULT", false, null, "../businessUtility/PrinterReports.html?inppdfpath=" + escape(strPagina) + "&inpdirectprint=" + escape(direct) + "&inphiddenkey=" + escape(strHiddenKey) + ((strHiddenValue!=null)?"&inphiddenvalue=" + escape(strHiddenValue):""), "frameOculto", null, bolComprobarCambios);
}

function abrirBusqueda(url, _name, tabId, windowName, windowId, checkChanges) {
  var parameters = new Array();
  parameters = addArrayValue(parameters, "inpTabId", tabId, true);
  parameters = addArrayValue(parameters, "inpWindow", windowName, true);
  parameters = addArrayValue(parameters, "inpWindowId", windowId, true);
  return openPopUp(url, _name, 450, 600, null, null, checkChanges, null, null, true, parameters);
}

function openHelp(windowId, url, _name, checkChanges, height, width, windowType, windowName) {
  if (height==null) height = 450;
  if (width==null) width = 700;
  var parameters = new Array();
  parameters = addArrayValue(parameters, "inpwindowId", windowId, true);
  parameters = addArrayValue(parameters, "inpwindowType", windowType, true);
  parameters = addArrayValue(parameters, "inpwindowName", windowName, true);
  return openPopUp(url, _name, height, width, null, null, checkChanges, null, null, true, parameters);
}

function openServletNewWindow(Command, depurar, url, _name, processId, checkChanges, height, width, resizable, hasStatus) {
  if (height==null) height = 350;
  if (width==null) width = 500;
  var parameters = new Array();
  parameters = addArrayValue(parameters, "scrollbars", "1");
  parameters = addArrayValue(parameters, "debug", depurar, false);
  if (processId!=null && processId!="") parameters = addArrayValue(parameters, "inpProcessId", processId, true);
  if (Command!=null && Command!="") parameters = addArrayValue(parameters, "Command", Command, false);
  return openPopUp(url, _name, height, width, null, null, checkChanges, null, true, true, parameters);
}

function openLink(url, _name, height, width) {
  return openNewLink(url, ((_name.indexOf("_")==0)?"":_name), height, width, null, null, null, ((_name.indexOf("_")==0)?_name:""), false, false, null);
}

function editHelp(url, tipo, id, value, height, width) {
  if (height==null) height = 500;
  if (width==null) width = 600;
  var parameters = new Array();
  parameters = addArrayValue(parameters, "Command", tipo, true);
  parameters = addArrayValue(parameters, "inpClave", value, true);
  return openPopUp(url, "HELP_EDIT", height, width, null, null, null, null, false, true, parameters);
}

/**
* @name pulsarTecla
* @format function pulsarTecla(CodigoTecla)
* @comment Esta función es interna y es ejecutada por otras funciones que activan el control de
*          eventos en una ventana HTML. Asocian esta función al evento <b>KeyDown</b> de la página, 
*          controlando así las pulsaciones de teclas en la página. Esta función se encarga de controlar
*          la pulsación de la tecla <em>ENTER<em>, para ejecutar una acción por defecto.
*
* @param <b>CodigoTecla</b> - Es el código ASCII de la tecla que se ha pulsado. Este código lo pasa
*         el propio controlador de eventos, por lo que no tenemos que preocuparnos de él.
* @return <b>true</b> - en caso de no haber pulsado ninguna de las teclas a controlar.<BR>
*         <b>false</b> - si se ha pulsado alguna de las teclas a controlar.
*/
function pulsarTecla(CodigoTecla)
{
  if (gBotonPorDefecto!=null)
  {
    var tecla = (!CodigoTecla) ? window.event.keyCode : CodigoTecla.which;
    if (tecla == 13)
    {
      eval(gBotonPorDefecto);
      return false;
    }
  }
  return true;
}


/**
* @name porDefecto
* @format function porDefecto(Accion)
* @comment Esta función se encarga de establecer una <b>Accion</b> por defecto en la página, es decir, 
*          la que se ejecutará al pulsar la tecla <em>ENTER</em>.<BR>
*          La <b>Accion</b> se le pasa en formato de texto, pero ha de ser un comando perfectamente 
*          ejecutable. No es bueno abusar de esta función, porque se pueden mezclar funciones. <BR>
*          Es importante saber que en las páginas de tipo frame, esta función es común a los frames, 
*          por lo que sólo podremos establecer en un frame esta función pero teniendo cuidado de que 
*          el usuario no pueda ponerse en otro frame pulsando <em>ENTER</em> porque, en tal caso, 
*          se ejecutará este comando igualmente, pudiéndo producirse algún error no deseado.
*
* @param <b>Accion</b> - es el comando que se debe ejecutar en caso de pulsar <em>ENTER</em>.
* @example porDefecto("alert('Hola')");
*/
function porDefecto(accion)
{
  gBotonPorDefecto = accion;
  if (!document.all)
  {
    document.captureEvents(Event.KEYDOWN);
  }
  document.onkeydown=pulsarTecla;
  return true;
}


/**
* @name Teclas
* @format function Teclas(tecla, evento, campo, teclaAuxiliar)
* @comment Esta función sirve para ir formando el array de teclas para cada pantalla.<BR>
*          Cada tecla que queremos utilizar debe contener esta estrtuctura.
*
* @param <b>tecla</b> - es la tecla que se debe pulsar en formato texto. No diferencia entre
*                       mayúsculas y minúsculas.<BR>
*        <b>evento</b> - Se trata de la acción que queremos que se ejecute cuando se pulse
*                        dicha tecla. Se le debe pasar el código a ejecutar como si fuese un
*                        strring.<BR>
*        <b>campo</b> - Se indica aquí el nombre de un campo de la ventana. Sirve para decir 
*                       que el evento se deverá ejecutar sólo si nos encontramos en ese campo. 
*                       Si este parámetro se deja null, estamos indicando que se trata de un evento 
*                       global, es decir, para toda la ventana.
*        <b>teclaAuxiliar</b> - Sus valores serán, <em>CTRL</em>, <em>ALT</em> ó <em>null</em>, 
*                               donde <em>CTRL</em> indica que se debe pulsar CONTROL a la que
*                               la tecla que se ha especificado, <em>ALT</em> indica que se debe
*                               pulsar ALTERNATIVA a la vez que la tecla indicada y <em>null</em> 
*                               indica que no se debe pulsar ninguna tecla a la vez.
* @example Teclas("A", "alert('Hola')", "inpcBpartnerId_D", null);
*/
function Teclas(tecla, evento, campo, teclaAuxiliar) {
  this.tecla = tecla;
  this.evento = evento;
  this.campo = campo;
  this.teclaAuxiliar = teclaAuxiliar;
}


/**
* @name obtenerCodigoTecla
* @format function obtenerCodigoTecla(codigo)
* @comment Se trata de una función interna que devuelve el código de la tecla que corresponde 
*          a la letra pasada.
*
* @param <b>codigo</b> - Es el texto que corresponde a la letra de la que queremos obtener su
*                        codigo de tecla.
* @return el código de la tecla de la letra pasada.
* @example obtenerCodigoTecla("A");
*/
function obtenerCodigoTecla(codigo) {
  if (codigo==null) return 0;
  else if (codigo.length==1) return codigo.toUpperCase().charCodeAt(0);
  switch (codigo.toUpperCase()) {
    case "BACKSPACE": return 8;
    case "TAB": return 9;
    case "ENTER": return 13;
    case "SPACE": return 32;
    case "DELETE": return 46;
    case "INSERT": return 45;
    case "END": return 35;
    case "HOME": return 36;
    case "REPAGE": return 33;
    case "AVPAGE": return 34;
    case "LEFTARROW": return 37;
    case "RIGHTARROW": return 39;
    case "UPARROW": return 38;
    case "DOWNARROW": return 40;
    case "NEGATIVE": return 189;
    case "NUMBERNEGATIVE": return 109;
    case "DECIMAL": return 190;
    case "NUMBERDECIMAL": return 110;
    case "ESCAPE": return 27;
    case "F1": return 112;
    case "F2": return 113;
    case "F3": return 114;
    case "F4": return 115;
    case "F5": return 116;
    case "F6": return 117;
    case "F7": return 118;
    case "F8": return 119;
    case "F9": return 120;
    case "F10": return 121;
    case "F11": return 122;
    case "F12": return 123;
    case "P": return 80;
/*    case "shiftKey": return 16;
    case "ctrlKey": return 17;
    case "altKey": return 18;*/
    default: return 0;
  }
}


/**
* @name controlTecla
* @format function controlTecla(CodigoTecla)
* @comment Se encarga de controlar la pulsación de teclas en una página, comprobando que 
*          no se pulse ninguna de las teclas especificadas en el array global arrTeclas, en
*          cuyo caso procede a ejecutar la acción asociada a dicha tecla en dicho array.
*
* @param <b>CodigoTecla</b> - Es el código de la tecla pulsada por el usuario.
* @return <b>true</b> - en caso de no pulsarse ninguna de las teclas del array.<BR>
*         <b>false</b> - en caso de pulsarse una tecla del array arrTeclas.
*/
function controlTecla(CodigoTecla) {
  if (arrTeclas==null || arrTeclas.length==0) return true;
  if (!CodigoTecla) CodigoTecla = window.event;
  var tecla = window.event ? CodigoTecla.keyCode : CodigoTecla.which;
  var target = (CodigoTecla.target?CodigoTecla.target: CodigoTecla.srcElement);
  //var target = (document.layers) ? CodigoTecla.target : CodigoTecla.srcElement;
  var total = arrTeclas.length;
  for (var i=0;i<total;i++) {
    if (arrTeclas[i]!=null && arrTeclas[i]) {
      if (tecla == obtenerCodigoTecla(arrTeclas[i].tecla)) {
        if (arrTeclas[i].teclaAuxiliar==null || arrTeclas[i].teclaAuxiliar=="" || arrTeclas[i].teclaAuxiliar=="null") {
          if (arrTeclas[i].campo==null || (target!=null && target.name!=null && isIdenticalField(arrTeclas[i].campo, target.name))) {
            var eventoTrl = replaceEventString(arrTeclas[i].evento, target.name, arrTeclas[i].campo);
            eval(eventoTrl);
            return false;
          }
        } else if (arrTeclas[i].campo==null || (target!=null && target.name!=null && isIdenticalField(arrTeclas[i].campo, target.name))) {
          if (arrTeclas[i].teclaAuxiliar=="ctrlKey" && CodigoTecla.ctrlKey && !CodigoTecla.altKey && !CodigoTecla.shiftKey) {
            var eventoTrl = replaceEventString(arrTeclas[i].evento, target.name, arrTeclas[i].campo);
            eval(eventoTrl);
            return false;
          } else if (arrTeclas[i].teclaAuxiliar=="altKey" && !CodigoTecla.ctrlKey && CodigoTecla.altKey && !CodigoTecla.shiftKey) {
            var eventoTrl = replaceEventString(arrTeclas[i].evento, target.name, arrTeclas[i].campo);
            eval(eventoTrl);
            return false;
          } else if (arrTeclas[i].teclaAuxiliar=="shiftKey" && !CodigoTecla.ctrlKey && !CodigoTecla.altKey && CodigoTecla.shiftKey) {
            var eventoTrl = replaceEventString(arrTeclas[i].evento, target.name, arrTeclas[i].campo);
            eval(eventoTrl);
            return false;
          }
        }
      }
    }
  }
  return true;
}

function isIdenticalField(nombreArray, nombreActual) {
  if (nombreArray.substring(nombreArray.length-1)=="%") return (nombreActual.indexOf(nombreArray.substring(0, nombreArray.length-1))==0);
  else return (nombreArray == nombreActual);
}

function replaceEventString(eventoJS, inputname, arrayName) {
  eventoJS = ReplaceText(eventoJS, "@inputname@", inputname);
  if (arrayName!=null && arrayName!="" && arrayName.substring(arrayName.length-1)=="%") {
    var endname = inputname.substring(arrayName.length-1);
    eventoJS = ReplaceText(eventoJS, "@endinputname@", endname);
  }
  return eventoJS;
}


/**
* @name activarControlTeclas
* @format function activarControlTeclas()
* @comment Es la encargada de activar el controlador de pulsación de teclas para la página.<BR>
*          Esta función se deberá activar tras haber definido el array de teclas global en dicha 
*          página, es decir, <em>arrTeclas</em>.
*
* @example onLoad="activarControlTeclas();"
*/
function activarControlTeclas() {
  if (arrTeclas==null || arrTeclas.length==0) return true;

    var agt=navigator.userAgent.toLowerCase();

/*	 if (agt.indexOf('gecko') != -1) { 
        document.releaseEvents(Event.KEYDOWN);
     }
  if (agt.indexOf('gecko') != -1)
    document.captureEvents(Event.KEYDOWN);*/
  
  document.onkeydown=controlTecla;
  return true;
}

/**
* @name rellenarComboHijo
* @format function rellenarComboHijo(combo, arrayDatos, padre, Selected, sinBlanco)
* @comment Esta función se encarga de rellenar un combo de datos, a partir de un array que se le pasa, 
*          buscando los elementos que contengan la clave padre indicada.
*
* @param <b>combo</b> - Es un objeto que identifica el combo a rellenar.<BR>
*        <b>arrayDatos</b> - Es un array con los datos que compondrán el combo. Este array debe estar
*                            compuesto por los siguientes campos en orden:<BR>
*                               <ol>
*                                 <li>Campo clave que representa el padre o elemento de agrupación de datos</li>
*                                 <li>Clave de cada elemento</li>
*                                 <li>Texto a presentar en el combo para cada elemento</li>
*                                 <li>Booleano que indica si se debe seleccionar o no</li>
*                               </ol>.<BR> 
*        <b>padre</b> - Es la clave del padre para buscar los elementos comunes a presentar.<BR>
*        <b>Selected</b> - Booleano que indica si se debe contemplar el último campo del array para seleccionar
*                          elementos dentro del nuevo array. Si este campo es null o false, no es necesario 
*                          implementar el último elemento del array de datos.<BR>
*        <b>sinBlanco</b> - Booleano que indica si se debe añadir o no un elemento en blanco. Para los combos 
*                           en los que se puede no elegir ningún elemento. Por defecto es false.
*
* @return Devuelve <b>true</b> si todo va bien y, si no, devuelve <b>false</b>.
* @example rellenarComboHijo(document.frmMain.inpCombo, arrDatos, '12', true, true);
*/
function rellenarComboHijo(combo, arrayDatos, padre, bolSelected, sinBlanco) {
  var i, value="";
  for (i = combo.options.length;i>=0;i--)
    combo.options[i] = null;
  i=0;
  if (sinBlanco==null || !sinBlanco)
    combo.options[i++] = new Option("", "");
  if (arrayDatos==null) return false;

  var total = arrayDatos.length;
  for (var j=0;j<total;j++) {
    if (arrayDatos[j][0]==padre) {
      combo.options[i] = new Option(arrayDatos[j][2], arrayDatos[j][1]);
      if (bolSelected!=null && bolSelected && arrayDatos[j][3]=="true") {
        value = arrayDatos[j][1];
        combo.options[i].selected = true;
      }
      else combo.options[i].selected = false;
      i++;
    }
  }
  return value;
}

/**
* @name layer
* @format function layer(Span, Texto, esId)
* @comment Esta función permite introducir un texto en objeto span, div o layer. Su finalidad es la 
*          de poder cambiar texto en una página HTML de forma dinámica sin que el texto deba estar en 
*          un campo de formulario.
*
* @param <b>Span</b> - Objeto que referencia a un span, div o layer de la página o el id de uno de 
*         esos objetos que exista en la página. <BR>
*        <b>Texto</b> - Texto que queremos que ponga en el span, div o layer. Si ponemos "", entonces,
*         lo deja vacío. <BR>
*        <b>esID</b> - Booleano que indica a la función si el primer parámetro que se le ha pasado es
*         el id (true) o el objeto (false). 
* @example layer("idSpan", "HOLA", true);
*/
function layer(nodo, strTexto, esId, isAppend)
{
  if (strTexto==null)
    strTexto = "";
  if (isAppend==null) isAppend=false;

  if (document.layers)
  {
    if (esId!=null && esId)
      nodo = document.layers[nodo];
    if (nodo==null) return;
    nodo.document.write(strTexto);
    nodo.document.close();
  }
  else if (document.all)
  {
    if (esId!=null && esId)
      nodo = document.all[nodo];
    if (nodo==null) return;
    //nodo.innerHTML = '';
    try {
      if (isAppend) {
        strTexto = ((nodo.innerHTML==null)?"":nodo.innerHTML) + strTexto;
        isAppend = false;
      }
      nodo.innerHTML = strTexto;
    } catch (e) {
      if (isAppend) {
        strTexto = ((nodo.outterHTML==null)?"":nodo.outterHTML) + strTexto;
        isAppend = false;
      }
      nodo.outterHTML = strTexto;
    }
    nodo=null;
  }
  else if (document.getElementById) 
  {
    if (esId!=null && esId)
      nodo = document.getElementById(nodo);
    if (nodo==null) return;
    var range = document.createRange();
    range.setStartBefore(nodo);
    var domfrag = range.createContextualFragment(strTexto);
    while (nodo.hasChildNodes())
    {
      nodo.removeChild(nodo.lastChild);
    }
    nodo.appendChild(domfrag);
    nodo=null;
  }
}

function readLayer(nodo, esId) {
  if (document.layers) {
    if (esId!=null && esId) nodo = document.layers[nodo];
    if (nodo==null) return "";
    return getChildText(nodo);
  } else if (document.all) {
    if (esId!=null && esId) nodo = document.all[nodo];
    if (nodo==null) return "";
    try {
      return nodo.innerHTML;
    } catch (e) {
      return nodo.outterHTML;
    }
  } else if (document.getElementById) {
    if (esId!=null && esId) nodo = document.getElementById(nodo);
    if (nodo==null) return "";
    return getChildText(nodo);
  }
  return "";
}

function getChildText(nodo) {
  if (nodo==null) return "";
  if (nodo.data) return nodo.data;
  else return getChildText(nodo.firstChild);
}


/**
* @name rellenarCombo
* @format function rellenarCombo(Combo, ArrayDatos, Selected, sinBlanco)
* @comment Rellena un <b>Combo</b> con los valores del <b>ArrayDatos</b>. Admite que se ponga un 
*          valor seleccionado en el <b>Combo</b>, que será el que se indique como tal en el 
*          <b>ArrayDatos</b>.
*
* @param <b>Combo</b> - referencia a un objeto del tipo combo, que es el que queremos rellenar con
*         los valores del <b>ArrayDatos</b>. <BR>
*        <b>ArrayDatos</b> - es un Array que contiene los valores que queremos que aparezcan en el
*         <b>Combo</b>. Su formato es (value, texto, selected), donde <em>valor</em> es el value que 
*         tendrá en <b>Combo</b>, <em>texto</em> es el texto que se verá en la lista desplegable y 
*         <em>selected</em> es un campo que tendrá el valor <strong>true</strong> o 
*         <strong>false</strong>, dependiendo de si queremos que ese registro aparezca seleccionado 
*         en el <b>Combo</b>. Este último campo (<em>selected</em>) sólo será necesario si queremos
*         que esta función establezca valos seleccionados en el <b>Combo</b>. <BR>
*        <b>Selected</b> - es un Booleano que indica si queremos que al rellenar el <b>Combo</b> se
*         ponga algún valor como seleccionado.<BR>
*        <b>sinBlanco</b> - para hacer que se elimine le primer elemento en blanco del combo. Recibe
*         valores booleanos.
*/
function rellenarCombo(combo, arrayDatos, bolSelected, sinBlanco) {
  var i, value="";
  for (i = combo.options.length;i>=0;i--)
    combo.options[i] = null;
  i=0;
  if (sinBlanco==null || !sinBlanco)
    combo.options[i++] = new Option("", "");
  if (arrayDatos==null) return "";

  var total = arrayDatos.length;
  for (var j=0;j<total;j++) {
    combo.options[i] = new Option(arrayDatos[j][1], arrayDatos[j][0]);
    if (bolSelected!=null && bolSelected && arrayDatos[j][2]=="true") {
      value = arrayDatos[j][0];
      combo.options[i].selected = true;
    }
    else combo.options[i].selected = false;
    i++;
  }
  return value;
}

/**
* @name selectDefaultValueFromArray
* @format function selectDefaultValueFromArray(arrayDatos, Selected)
* @comment Esta función se encarga de buscar el elemento seleccionado dentro de un array de datos. En 
*          caso de no encontrar ningún elemento seleccionado elige el primero.
*
* @param <b>arrayDatos</b> - Es un array que contiene los datos. Su formato es de 3 campos en el siguiente 
*         orden: primero la clave, luego el texto del elemento y, por último, un booleano que indica si el 
*         elemento está seleccionado o no.<BR>
*        <b>Selected</b> - Booleano que indica si debe buscar un elemento seleccionado dentro del array. Si 
*         este parámetro se deja a null o es false, se presentará el primer elemento del array.
*
* @return Devuelve un valor en blanco si no encuentra ningún dato o el array está vacío. Devolverá la clave 
*         del elemento correspondiente en caso de realizar correctamente la búsqueda.
* @example selectDefaultValueFromArray(arrDatos, true);
*/
function selectDefaultValueFromArray (arrayDatos, bolSelected) {
  var value="";
  if (arrayDatos==null) return "";

  value = arrayDatos[0][0];
  var total = arrayDatos.length;
  for (var j=0;j<total;j++) {
    if (bolSelected!=null && bolSelected && arrayDatos[j][2]=="true") {
      value = arrayDatos[j][0];
    }
  }
  return value;
}

/**
* @name changeOrderBy
* @format function changeOrderBy(list)
*/
function changeOrderBy(sourceList) {
  if (sourceList == null) return false;
  for (var j=sourceList.length-1;j>=0;j--) {
    if (sourceList.options[j].selected==true) {
      var text = sourceList.options[j].text;
      var value = sourceList.options[j].value;
      if (value.indexOf("-")!=-1) {
        value = value.substring(1);
        text = text.substring(2);
        text = "/\\" + text;
      } else {
        value = "-" + value;
        text = text.substring(2);
        text = "\\/" + text;
      }
      
      sourceList.options[j].value = value;
      sourceList.options[j].text = text;
    }
  }
  return true;
}

/**
* @name addListOrderBy
* @format function addListOrderBy(list, listDestino, prefix, all)
*/
function addListOrderBy(sourceList, destinationList, withPrefix, selectAll) {
  if (sourceList==null || destinationList==null) return false;
  if (selectAll==null) selectAll=false;
  if (withPrefix==null) withPrefix=false;
  for (var j=sourceList.length-1;j>=0;j--) {
    if (selectAll || sourceList.options[j].selected==true) {
      var text = sourceList.options[j].text;
      var value = sourceList.options[j].value;
      if (withPrefix) {
        if (value.indexOf("-")!=-1) value = value.substring(1);
        if (text.indexOf("/\\")!=-1 || text.indexOf("\\/")!=-1) text = text.substring(2);
      } else {
        text = "/\\" + text;
      }
      destinationList.options[destinationList.length] = new Option(text, value);
      sourceList.options[j]=null;
    }
  }
  return true;
}

/**
* @name addList
* @format function addList(list, listDestino, all)
* @comment Se encarga de trasladar los elementos de un list a otro. Puede trasladar los elementos
*          seleccionados o todos.
*
* @param <b>list</b> - Es un objeto que referencia al list de origen de los datos a copiar.<BR>
*        <b>listDestino</b> - Es un objeto que referencia al list donde se van a copiar los elementos.<BR>
*        <b>all</b> - Es un booleano que indica se copiamos solo los seleccionados o todos.
*
* @return Devuelve <b>true</b> si se ha podido procesar o <b>false</b> en caso contrario.
* @example addList(document.frmMain.inpList1, document.frmMain.inpList2, false);
*/
function addList(sourceList, destinationList, selectAll) {
  if (sourceList==null || destinationList==null) return false;
  if (selectAll==null) selectAll=false;
  for (var j=sourceList.length-1;j>=0;j--) {
    if (selectAll || sourceList.options[j].selected==true) {
      destinationList.options[destinationList.length] = new Option(sourceList.options[j].text, sourceList.options[j].value);
      sourceList.options[j]=null;
    }
  }
  return true;
}

/**
* @name moveElementInList
* @format function moveElementInList(list, incremento)
* @comment Mueve el elemento o elementos seleccionados dentro de un list, incrementando su posición en el
*          valor del incremento.<BR>
*          Si el incremento es negativo mueve los elementos hacia arriba y si no, hacia abajo.
*
* @param <b>list</b> - Es un objeto que referencia al list en el que queremos mover los elementos.<BR>
*        <b>incremento</b> - Es un entero que indica el número de posiciones a mover los elementos y 
*         el signo del desplazamiento. Si no se indica es 1.
*
* @return Devuelve <b>true</b> si se puede realizar la operación o <b>false</b> en caso contrario.
* @example moveElementInList(document.frmMain.inpList, -1);
*/
function moveElementInList(list, incr) {
  if (list==null) return false;
  else if (list.length<2) return false;
  if (incr==null) incr=1;
  if (incr>0) {
    for (var i=list.length-2;i>=0;i--) {
      if (list.options[i].selected==true && ((i+incr)>=0 || (i+incr)<list.length)) {
        list.options[i].selected=false;
        var text = list.options[i+incr].text;
        var value = list.options[i+incr].value;
        list.options[i+incr].value = list.options[i].value;
        list.options[i+incr].text = list.options[i].text;
        list.options[i+incr].selected=true;
        list.options[i].value = value;
        list.options[i].text = text;
      }
    }
  } else {
    var total = list.length;
    for (var i=1;i<total;i++) {
      if (list.options[i].selected==true && ((i+incr)>=0 || (i+incr)<list.length)) {
        list.options[i].selected=false;
        var text = list.options[i+incr].text;
        var value = list.options[i+incr].value;
        list.options[i+incr].value = list.options[i].value;
        list.options[i+incr].text = list.options[i].text;
        list.options[i+incr].selected=true;
        list.options[i].value = value;
        list.options[i].text = text;
      }
    }
  }
  return true;
}


/**
* @name valorArray
* @format function valorArray(ArrayDatos, Clave, Posicion)
* @comment Devuelve el valor del campo que está en la <b>Posicion</b> indicada, del registro cuyo
*          primer campo tenga el valor <b>Clave</b>.
*
* @param <b>ArrayDatos</b> - Array que contiene los registros entre los que buscar. <BR>
*        <b>Clave</b> - Valor que hay que buscar en el primer campo del <b>ArrayDatos</b>. <BR>
*        <b>Posicion</b> - Posición del campo que contiene la descripción que queremos obtener. De
*           este modo, podemos devolver cualquier campo del array
* @return Devuelve el valor del campo indicado o blanco si no se encuentra ningún registro con esa
*         <b>Clave</b>.
*/
function valorArray(arrDatos, strClave, intDevolverPosicion)
{
  if (arrDatos == null) return "";
  else if (strClave==null) return "";
  if (intDevolverPosicion==null) intDevolverPosicion = 1;

  var total = arrDatos.length;
  for (var i=0;i<total;i++) {
    if (arrDatos[i][0] == strClave) {
      return arrDatos[i][intDevolverPosicion];
    }
  }
  return "";
}


/**
* @name radioValue
* @format function radioValue(Radio)
* @comment Se encarga de obtener el valor seleccionado de un radio button que exista en la página. La
*          complejida de esta función viene en que sirve tanto para obtener el valor seleccionado 
*          cuando sólo hay un campo asociado al radio button que se le pase y, también, cuando sean 
*          más de uno, como en el caso de una lista de valores de entre los que sólo podemos elegir 
*          uno y que están representados por radio buttons.
*
* @param <b>Radio</b> - es un objeto que referencia al radio button del que queremos sacar el valor 
*           seleccionado.
* @return Devuelve el valor seleccionado o null en caso de encontrarlo.
* @example radioValue(document.forms[0].inpRadioButton);
*/
function radioValue(radio)
{
  if (!radio) return null;
  else if (!radio.length)
    return ((radio.checked)?radio.value:null);
  var total = radio.length;
  for (var i=0;i<total;i++)
  {
    if (radio[i].checked)
      return radio[i].value;
  }
  return null;
}


/**
* @name marcarTodos
* @format function marcarTodos(Check, Marcar)
* @comment Es muy útil, porque se encarga de marcar o desmarcar todos los checkBox, asociados al 
*          checkBox que se le pase. Se ha utilizado para los links de marcar y desmarcar todos de 
*          las páginas que tienen un checkbox por cada línea que presentan y se permite seleccionar 
*          mediante los checks una o más de una para realizar operaciones con las mismas. Lo bueno 
*          de esta función es que es independiente el hecho de que exista sólo un checkBox asociado 
*          o más.
*
* @param <b>Check</b> - es un objeto que referencia al check de la página que queremos marcar o 
*           desmarcar. <BR>
*        <b>Marcar</b> - es un booleano que indica si la operación a realizar es la de marcar o 
*           la de desmarcar.
* @return <b>false</b> - en caso de no encontrar el check indicado. <BR>
*         <b>true</b> - en los demás casos.
* @example marcarTodos(document.TITULOS.inpCheck, true);
*/
function marcarTodos(chk, bolMarcar)
{
  if (bolMarcar==null) bolMarcar = false;
  if (!chk) return false;
  else if (!chk.length) chk.checked = bolMarcar;
  else {
    var total = chk.length;
    for (var i=0;i<total;i++) chk[i].checked = bolMarcar;
  }
  return true;
}

/**
* @name cambiarListaCombo
* @format function cambiarListaCombo(combo, arrayDatos, clave, blanco)
* @comment Para los arrays que se recargan desde la propia página al cambiar el valor seleccionado 
*          en algún otro combo
*
* @param <b>combo</b> - es un objeto que referencia al combo que queremos rellenar con los nuevos 
*           valores.<BR>
*        <b>arrayDatos</b> - Es el array que contiene los datos que van a formar los valores del
*           combo.<BR>
*        <b>clave</b> - Es el valor de la clave que identifica los valores que hay que poner en el
*           combo. Es el valor del primer campo del array.<BR>
*        <b>blanco</b> - Es un booleano que indica si hay que poner un elemento en blanco (true) en
*           el combo o no (false).
* @example cambiarListaCombo(document.frmEdicion.inpCombo, arrayProvincias, "1", false);
*/
function cambiarListaCombo(combo, arrayDatos, clave, blanco) {
  var i;
  var n=0;
  if (combo.options.length!=null) {
    for (i = combo.options.length;i>=0;i--)
      combo.options[i] = null;
  }

  if (blanco)
    combo.options[n++] = new Option("", "");
  if (arrayDatos==null) return false;

  var total = arrayDatos.length;
  for (i=0;i<total;i++) {
    if (arrayDatos[i][0]==clave)
      combo.options[n++] = new Option(arrayDatos[i][2], arrayDatos[i][1]);
  }
}


/**
* @name limpiarList
* @format function limpiarList(campo)
* @comment Borra todos los elementos de un list.
*
* @param <b>campo</b> - Objeto que referencia el combo que queremos vaciar.
*
* @return Devuelve <b>true</b> si puede procesar la operación o <b>false</b> en caso contrario.
* @example limpiarList(document.frmMain.inpList);
*/
function limpiarLista(campo) {
  if (campo==null) return false;
  for (var i = campo.options.length - 1;i>=0;i--) campo.options[i] = null;
  return true;
}

/**
* @name eliminarElementosList
* @format function eliminarElementosList(campo)
* @comment Esta función se utiliza en los selectores múltiples para el paso de elementos entre lists, 
*          encargándose de la eliminación de los elementos seleccionados.
*
* @param <b>campo</b> - Es un objeto que referencia al list del que queremos eliminar elmentos.
*
* @return Devuelve <b>true</b> si se puede procesar o <b>false</b> en caso contrario.
* @example eliminarElementosList(document.frmMain.inpList);
*/
function eliminarElementosList(campo) {
  if (campo==null) return false;
  for (var i = campo.options.length - 1;i>=0;i--) {
    if (campo.options[i].selected) campo.options[i] = null;
  }
  return true;
}

/**
* @name generarArrayChecks
* @format function generarArrayChecks(Formulario, checkbox, textbox, resultado)
* @comment Genera un array a partir de los datos de los checkbox seleccionados y con el texto de los textbox 
*          indicados.
*
* @param <b>Formulario</b> - Es un objeto que referencia al formulario donde se encuentran los check y textbox.<BR>
*        <b>checkbox</b> - Es un objeto que referencia a los checkbox que contienen los valores seleccionados.<BR>
*        <b>textbox</b> - Es un string que contiene el nombre del textbox que contiene el texto a presentar del array.<BR>
*        <b>resultado</b> - Es el array en el que se devolverán los datos del combo. Se trata de un 
*         parámetro de salida.
*
* @example generarArrayChecks(document.frmMain.inpCombo, arrDatos);
*/
function generarArrayChecks(frm, check, text, resultado) {
  var n=0;
  if (check==null) {
    resultado=null;
    return;
  }
  if (!check.length || check.length<=1) {
    if (check.checked) {
      var texto = eval(frm.name + "." + text + check.value);
      var valor = "";
      if (texto!=null) {
        if (!texto.length || texto.length<=1) valor = texto.value;
        else valor = texto[0].value;
      }
      resultado[0] = new Array(check.value, valor);
    }
  } else {
    for (var i = check.length-1;i>=0;i--) {
      if (check[i].checked) {
        var valor = "";
        var texto = eval(frm.name + "." + text + check[i].value);
        if (texto!=null) {
          if (!texto.length || texto.length<=1) valor = texto.value;
          else valor = texto[0].value;
        }
        resultado[n++] = new Array(check[i].value, valor);
      }
    }
  }
}

/**
* @name estaEnCombo
* @format function estaEnCombo(combo, clave)
* @comment Se encarga de buscar una clave en un combo y devolver un booleano que indica si la ha encontrado o no.
*
* @param <b>combo</b> - Es un objeto que referencia al combo en el que buscamos la clave.<BR>
*        <b>clave</b> - Es la clave que buscamos en el combo.
*
* @return Devuelve <b>true</b> si se encuentra la clave en el combo o <b>false</b> en caso contrario.
* @example estaEnCombo(document.frmMain.inpCombo, '12');
*/
function estaEnCombo(combo, clave) {
  if (combo==null || clave==null) return false;
  var total = combo.options.length;
  for (var i=0;i<total;i++) {
    if (combo.options[i].value == clave) return true;
  }
  return false;
}

/**
* @name insertarElementosList
* @format function insertarElementosList(campo, arrayDatos)
* @comment Sirve para introducir valores nuevos en un list.
*
* @param <b>campo</b> - Es un objeto que referencia al campo sobre el que queremos añadir valores.<BR>
*        <b>arrayDatos</b> - Es el array con los nuevos datos a añadir.
*
* @return Devuelve <b>true</b> si se puede procesar o <b>false</b> si hay algún problema.
* @example insertarElementosList(document.frmMain.inpList, arrDatos);
*/
function insertarElementosList(campoDestino, arrayValores) {
  if (campoDestino == null || arrayValores == null) return false;
  var i = campoDestino.options.length;
  var total = arrayValores.length;
  for (var j=0; j<total;j++) {
      if (!estaEnCombo(campoDestino, arrayValores[j][0]))
        campoDestino.options[i++] = new Option(arrayValores[j][1], arrayValores[j][0]);
  }
  return true;
}

/**
* @name seleccionarListCompleto
* @format function seleccionarListCompleto(campo)
* @comment Se encarga de seleccionar todos los elementos de un list o combo. Se utiliza para los selectores 
*          múltiples, donde se deben marcar todos los valores elegidos antes de hacer el submit de la ventana.
*
* @param <b>campo</b> - Es un objeto que referencia al campo que queremos seleccionar.
*
* @return Devuelve <b>true</b> si se procesa correctamente o <b>false</b> si no existe el campo.
* @example seleccionarListCompleto(document.frmMain.inpList);
*/
function seleccionarListCompleto(campo) {
  if (campo==null || campo==null) return false;
  var total = campo.options.length;
  for (var i=0;i<total;i++) {
    campo.options[i].selected = true;
  }
  return true;
}

/**
* @name tamanoMaximo
* @format function tamanoMaximo(campo, tamano)
* @comment Es un manejador de eventos que controla las pulsaciones de teclas en los textarea, 
*          donde no se puede controlar el tamaño del texto que se introduce. Con esta función 
*          podemos controlar que el usuario no introduce un texto mayor del que podemos almacenar, 
*          presentando un mensaje en caso de superar el límite.
*
* @param <b>campo</b> - Es un objeto que referencia al campo sobre el que ponemos el control. normalmente 
*         usuaremos el objeto this.<BR>
*        <b>tamano</b> - Es el tamaño máximo de texto que permitiremos introducir.
*
* @return Devuelve <b>true</b> si se permite seguir introduciendo texto o <b>false</b> en caso contrario.
* @example onKeyDown="return tamanoMaximo(this, 50);"
*/
function tamanoMaximo(campo, tamano, evt) {
  if (campo==null || !campo) return false;
  if (campo.value.length>=tamano) {
    if (document.layers) CodigoTecla.which=0;
    else {
      if (evt==null) evt = window.event;
      evt.keyCode=0;
      evt.returnValue = false;
      evt.cancelBubble = true 
    }
    mensaje(11);
    return false;
  }
  return true;
}

/**
* @name selectCombo
* @format function selectCombo(combo, clave)
* @comment Selecciona un elemento dentro de un combo.
*
* @param <b>combo</b> - Es una referencia al combo en el que queremos seleccionar un elemento.<BR>
*        <b>clave</b> - Es la clave del elemento que queremos seleccionar.
*
* @return Devuelve un booleano que indica si ha podido procesar la operación o no.
* @example selectCombo(document.frmMain.inpCombo, '12');
*/
function selectCombo(combo, clave) {
  if (!combo || combo==null) return false;
  var total = combo.length;
  for (var i=0;i<total;i++) {
    combo.options[i].selected = (combo.options[i].value == clave);
  }
  return true;
}

function updateMenuIcon(id) {
  if (!top.frameMenu) return false;
  else {
    var frame = top.document;
    var frameset = frame.getElementById("framesetMenu");
    if (!frameset) return false;
    try {
      if (frameset.cols.substring(0,1)=="0") changeClass(id, "_hide", "_show", true);
      else changeClass(id, "_show", "_hide", true);
    } catch (ignored) {}
    return true;
  } 
}

/**
* @name mostrarMenu
* @format function mostrarMenu()
* @comment Muestra u oculta el menu de la ventana de la aplicación.
*
* @return Devuelve un booleano que indica si ha podido procesar la operación o no.
* @example onClick="mostrarMenu();return false;"
*/
function mostrarMenu(id) {
  if (!top.frameMenu) window.open(baseFrameServlet, "_blank");
  else {
    var frame = top.document;
    var frameset = frame.getElementById("framesetMenu");
    if (!frameset) return false;
    /*try {
      var frm2 = frame.getElementById("frameMenu");
      var obj = document.onresize;
      var obj2 = frm2.onresize;
      document.onresize = null;
      frm2.document.onresize = null;
      progressiveHideMenu("framesetMenu", 30);
      document.onresize = obj;
      frm2.document.onresize = obj2;
    } catch (e) {*/
      if (frameset.cols.substring(0,1)=="0") frameset.cols = "25%,*";
      else  frameset.cols = "0%,*";
    //}
    try {
      changeClass(id, "_hide", "_show");
    } catch (e) {}
    return true;
  }
}

function progressiveHideMenu(id, topSize, newSize, grow) {
  var frame = top.document;
  var object = frame.getElementById(id);
  if (newSize==null) {
    var sizes = object.cols.split(",");
    size = sizes[0];
    size = size.replace("%", "");
    size = size.replace("px", "");
    newSize = parseInt(size);
  }
  if (grow==null) grow = !(newSize>0);
  if (grow) {
    newSize += 5;
    if (newSize>=topSize) {
      object.cols = topSize + "%, *";
      return true;
    } else object.cols = newSize + "%, *";
  } else {
    newSize -= 5;
    if (newSize<=0) {
      object.cols = "0%, *";
      return true;
    } else object.cols = newSize + "%, *";
  }
  return setTimeout('progressiveHideMenu("' + id + '", ' + topSize + ', ' + newSize + ', ' + grow + ')', 100);
}

function changeClass(id, class1, class2, forced) {
  if (forced==null) forced = false;
  var element = document.getElementById(id);
  if (!element) return false;
  if (element.className.indexOf(class1)!=-1) element.className = element.className.replace(class1, class2);
  else if (!forced && element.className.indexOf(class2)!=-1) element.className = element.className.replace(class2, class1);
  return true;
}

/**
* @name getReference
* @format function getReference(id)
* @comment Función interna para obtener la referencia a un objeto de la ventana del que recivimos 
*          su id.
*
* @param <b>id</b> - Es el id del elemento.
*
* @return Devuelve una referencia al objeto o null si no lo encuentra.
* @example getReference('paramField');
*/
function getReference(id) {
  if (document.getElementById) return document.getElementById(id);
  else if (document.all) return document.all[id];
  else if (document.layers) return document.layers[id];
  else return null;
}

/**
* @name getStyle
* @format function getStyle(id)
* @comment Función interna para obtener la propiedad style de un elemento del que se pasa su id.
*
* @param <b>id</b> - Es el id del elemento del que queremos obtener su style.
*
* @return Devuelve una referencia a la propiedad style del elemento o null si no lo encuentra.
* @example getStyle('paramField');
*/
function getStyle(id) {
  var ref = getReference(id);
  if (ref==null || !ref) return null;
  return ((document.layers) ? ref : ref.style);
}

/**
* @name idName
* @format function idName(name)
*/
function idName(name) {
  return (name.substring(0,9) + name.substring(10));
}

/**
* @name findElementPosition
* @format function findElementPosition(Formulario, name)
*/
function findElementPosition(Formulario, name) {
  var total = Formulario.length;
  for (var i=0;i<total;i++) {
    if (Formulario.elements[i].name==name) return i;
  }
  return null;
}

/**
* @name deselectActual
* @format function deselectActual(Formulario, field)
*/
function deselectActual(Formulario, field) {
  if (field==null || field.value==null || field.value=="") return null;
  var i=findElementPosition(Formulario, "inpRecordW" + field.value);
  if (i==null) return null;
  recordSelectExplicit("inpRecord" + field.value, false);
  field.value="";
  return i;
}

/**
* @name findFirstElement
* @format function findFirstElement(Formulario)
*/
function findFirstElement(Formulario) {
  if (Formulario==null) return null;
  var n=null;
  var total = Formulario.length;
  for (var i=0;i<total;i++) {
    if (Formulario.elements[i].name.indexOf("inpRecordW")==0) {
      n=i;
      break;
    }
  }
  return n;
}

/**
* @name findLastElement
* @format function findLastElement(Formulario)
*/
function findLastElement(Formulario) {
  if (Formulario==null) return null;
  var n=null;
  for (var i=Formulario.length-1;i>=0;i--) {
    if (Formulario.elements[i].name.indexOf("inpRecordW")==0) {
      n=i;
      break;
    }
  }
  return n;
}

/**
* @name nextElement
* @format function nextElement(Formulario, field)
*/
function nextElement(Formulario, field) {
  var i=deselectActual(Formulario, field);
  if (i==null) {
    i=findFirstElement(Formulario);
    if (i==null) return;
  } else if (i<findLastElement(Formulario)) i++;
  field.value = Formulario.elements[i].name.substring(10);
  recordSelectExplicit("inpRecord" + Formulario.elements[i].name.substring(10) , true);
  Formulario.elements[i].focus();
  return true;
}

/**
* @name previousElement
* @format function previousElement(Formulario, field)
*/
function previousElement(Formulario, field) {
  var i=deselectActual(Formulario, field);
  var menor = findFirstElement(Formulario);
  if (menor==null) return;
  else if (i==null) {
    i=menor;
    if (i==null) return;
  } if (i>menor) i--;
  field.value = Formulario.elements[i].name.substring(10);
  recordSelectExplicit("inpRecord" + Formulario.elements[i].name.substring(10) , true);
  Formulario.elements[i].focus();
  return true;
}

/**
* @name firstElement
* @format function firstElement(Formulario, field)
*/
function firstElement(Formulario, field) {
  var i=deselectActual(Formulario, field);
  i=findFirstElement(Formulario);
  if (i==null) return;
  field.value = Formulario.elements[i].name.substring(10);
  recordSelectExplicit("inpRecord" + Formulario.elements[i].name.substring(10) , true);
  Formulario.elements[i].focus();
  return true;
}

/**
* @name lastElement
* @format function lastElement(Formulario, field)
*/
function lastElement(Formulario, field) {
  var i=deselectActual(Formulario, field);
  i=findLastElement(Formulario);
  if (i==null) return;
  field.value = Formulario.elements[i].name.substring(10);
  recordSelectExplicit("inpRecord" + Formulario.elements[i].name.substring(10) , true);
  Formulario.elements[i].focus();
  return true;
}

/**
* @name recordSelectExplicit
* @format function recordSelectExplicit(name, seleccionar)
*/
function recordSelectExplicit(name, seleccionar) {
  var obj = getStyle(name);
  if (obj==null) return false;
  if (document.layers) {
    if (seleccionar) obj.bgColor=gColorSelected;
    else obj.bgColor=gWhiteColor;
  } else {
    if (seleccionar) obj.backgroundColor = gColorSelected;
    else obj.backgroundColor=gWhiteColor;
  }
  return seleccionar;
}

/**
* @name selectRadioButton
* @format function selectRadioButton(radio, value)
* @comment Selecciona un valor dentro de un grupo de radio buttons
*
* @param <b>radio</b> - Es una referencia al radio button.<BR>
*        <b>value</b> - Es el value del radio button que queremos seleccionar.
*
* @return Devuelve <b>true</b> si todo va bien o <b>false</b> en caso contrario.
* @example selectRadioButton(document.frmMain.inpRadio, '12');
*/
function selectRadioButton(radio, Value) {
  if (!radio) return false;
  else if (!radio.length) radio.checked=true;
  else {
    var total = radio.length;
    for (var i=0;i<total;i++) radio[i].checked = (radio[i].value==Value);
  }
  return true;
}
/**
* @name selectCheckbox
* @format function selectCheckbox(obj, value)
* @comment Selecciona un valor dentro de un grupo de radio buttons
*
* @param <b>obj</b> - Es una referencia al checked.<BR>
*        <b>value</b> - Es el value del radio button que queremos seleccionar.
*
* @return Devuelve <b>true</b> si todo va bien o <b>false</b> en caso contrario.
* @example selectCheckbox(document.frmMain.inpChecked, '12');
*/
function selectCheckbox(obj, Value) {

  if (!obj) return false;
  else {
    obj.checked = (obj.value==Value);
  }
  return true;
}


/**
* @name formElementValue
* @format function formElementValue(Formulario, ElementName, Value)
*/
function formElementValue(Formulario, ElementName, Value) {
  var bolReadOnly=false;
  var onChangeFunction = "";
  if (Formulario==null) {
    Formulario=document.forms[0];
    if (Formulario==null) return false;
  } else if (ElementName==null) return false;
  if (ElementName=="MESSAGE") {
    try {
      setValues_MessageBox('messageBoxID', "INFO", "", Value);
    } catch (err) {
      alert(Value);
    }
  } else if (ElementName=="ERROR" || ElementName=="SUCCESS" || ElementName=="WARNING" || ElementName=="INFO") {
    try {
      setValues_MessageBox('messageBoxID', ElementName, "", Value);
    } catch (err) {
      alert(Value);
    }
  } else if (ElementName=="EXECUTE") {
    eval(Value);
  } else if (ElementName=="DISPLAY") {
    displayLogicElement(Value, true);
  } else if (ElementName=="HIDE") {
    displayLogicElement(Value, false);
  } else if (ElementName=="CURSOR_FIELD") {
    var obj = eval("document." + Formulario.name + "." + Value + ";");
    if (obj==null || !obj || !obj.type || obj.type.toUpperCase()=="HIDDEN") return false;
    obj.focus()
    if (obj.type.toUpperCase().indexOf("SELECT")==-1) obj.select();
    //document.focus();
  } else {
    if (ElementName.indexOf("_BTN")!=-1) {
      if (Value==null || Value=="null") Value="";
      layer(ElementName, Value, true);
      return true;
    }
    var obj = eval("document." + Formulario.name + "." + ElementName + ";");
    if (obj==null || !obj || !obj.type) return false;
    if (obj.getAttribute("readonly")=="true") bolReadOnly=true;
    if (bolReadOnly) {
      onChangeFunction = obj.onchange;
      obj.onchange = "";
      obj.setAttribute("readonly", "false");
      //obj.readOnly="false";
    }
    if (obj.type.toUpperCase().indexOf("SELECT")!=-1) {
      if (Value!=null && typeof Value!="object") {
        var total = obj.length;
        var index = -1;
        var hasMultiSelect = false;
        var selectedOption = false;
        if ((Value==null || Value=="") && total>0) Value = obj.options[0].value;
        for (var i=0;i<total;i++) {
          selectedOption = (obj.options[i].value == Value);
          obj.options[i].selected = selectedOption;
          if (selectedOption) {
            if (index!=-1) hasMultiSelect = true;
            index = i;
          }
        }
        if (!hasMultiSelect) obj.selectedIndex = index;
      } else Value = rellenarCombo(obj, Value, true, ((obj.className.toUpperCase().indexOf("REQUIRED")!=-1) || obj.className.toUpperCase().indexOf("KEY")!=-1 || (obj.className.toUpperCase().indexOf("READONLY")!=-1)));
    } else if (obj.type.toUpperCase().indexOf("CHECKBOX")!=-1) {
      selectCheckbox(obj, Value);
    } else if (obj.type.toUpperCase().indexOf("RADIO")!=-1 || obj.type.toUpperCase().indexOf("CHECK")!=-1) {
      selectRadioButton(obj, Value);
    } else {
      if (Value==null || Value=="null") Value="";
      if (typeof Value!="object") {
        obj.value = Value;
      } else //if (obj.className.toUpperCase().indexOf("REQUIRED")!=-1 || obj.className.toUpperCase().indexOf("KEY")!=-1 || obj.className.toUpperCase().indexOf("READONLY")!=-1) 
        obj.value = selectDefaultValueFromArray(Value, true);
    }
    if (bolReadOnly && onChangeFunction) {
      var i = onChangeFunction.toString().indexOf("selectCombo(this,");
      var search = "\"";
      if (i!=-1) {
        var first = onChangeFunction.toString().indexOf(search, i+1);
        if (first==-1) {
          search = "'";
          first = onChangeFunction.toString().indexOf(search, i+1);
        }
        if (first!=-1) {
          var end = onChangeFunction.toString().indexOf(search, first+1);
          if (end!=-1) {
            onChangeFunction = onChangeFunction.toString().substring(0, first+1) + Value + onChangeFunction.toString().substring(end);
            onChangeFunction = onChangeFunction.toString().replace("function anonymous()", "");
          }
        }
      }
      if (onChangeFunction.toString().indexOf("function anonymous()")==-1) obj.onchange = new Function("", onChangeFunction.toString());
      else obj.onchange = onChangeFunction.toString();
      //obj.onchange = function anonymous() {selectCombo(this, Value);return true;};
      obj.setAttribute("readonly", "true");
    }
  }
  return true;
}

function setClass(id, selectClass) {
  var obj = getReference(id);
  if (obj==null) return null;
  obj.className = selectClass;
}

function getObjectClass(id, previousClass) {
  var obj = getReference(id);
  if (obj==null) return previousClass;
  return(obj.className);
}

/**
* @name formElementEvent
* @format function formElementEvent(Formulario, ElementName, callout)
*/
function formElementEvent(Formulario, ElementName, calloutName) {
  if (Formulario==null) Formulario=document.forms[0].name;
  else if (ElementName==null) return false;
  var isReload=false;
  if (ElementName!="MESSAGE" && ElementName!="CURSOR_FIELD" && ElementName!="EXECUTE" && ElementName!="DISPLAY" && ElementName!="HIDE" && ElementName.indexOf("_BTN")==-1) {
    var obj = eval("document." + Formulario + "." + ElementName + ";");
    if (obj==null || !obj || !obj.type) return false;
    if (obj.type.toUpperCase().indexOf("RADIO")!=-1) {
      if (obj.onclick!=null && obj.onclick.toString().indexOf(calloutName)==-1) {
        if (obj.onclick.toString().indexOf("callout")!=-1 || obj.onclick.toString().indexOf("reload")!=-1) isReload=true;
        obj.onclick();
      }
    } else {
      var bolReadOnly = false;
      if (obj.onchange!=null && obj.onchange.toString().indexOf(calloutName)==-1) {
        if (obj.onchange.toString().indexOf("callout")!=-1 || obj.onchange.toString().indexOf("reload")!=-1) isReload=true;
        if (obj.getAttribute("readonly")=="true") {
          bolReadOnly=true;
          obj.removeAttribute("readonly");
        }
        obj.onchange();
        if (bolReadOnly) obj.setAttribute("readonly", "true");
      }
    }
  }
  return (isReload);
}

/**
* @name fillElements
* @format function fillElements(Formulario, name, callout)
*/
function fillElements(frm, name, callout) {
  this.formName = frm;
  this.name = name;
  this.callout = callout;
}

/**
* @name fillElementsFromArray
* @format function fillElementsFromArray(arrElements, calloutName, Fromulario)
*/
function fillElementsFromArray(arrElements, calloutName, Formulario) {
  gWaitingCallOut=false;
  if (arrElements==null && arrGeneralChange==null) return false;
  if (Formulario==null || !Formulario) Formulario=document.forms[0];
  if (arrElements!=null) {
    var total = arrElements.length;
    for (var x=0;x<total;x++) {
      formElementValue(Formulario, arrElements[x][0], arrElements[x][1]);
    }
  }
  if (arrGeneralChange==null) arrGeneralChange=new Array();
  if (arrElements!=null) {
    var n=arrGeneralChange.length;
    var total = arrElements.length;
    for (var x=0;x<total;x++) {
        arrGeneralChange[x+n] = new fillElements(Formulario.name , arrElements[x][0], calloutName);
    }
  }
  while (arrGeneralChange!=null && arrGeneralChange.length>0) {
    var obj = arrGeneralChange[0].formName;
    var name = arrGeneralChange[0].name;
    var callout = arrGeneralChange[0].callout;
    {
      if (arrGeneralChange==null || arrGeneralChange.length==0) return true;
      var arrDataNew = new Array();
      var total = arrGeneralChange.length;
      for (var i=1;i<total;i++) {
        arrDataNew[i-1] = new fillElements(arrGeneralChange[i].formName, arrGeneralChange[i].name, arrGeneralChange[i].callout);
      }
      arrGeneralChange=null;
      arrGeneralChange = new Array();
      total = arrDataNew.length;
      for (var i=0;i<total;i++) {
        arrGeneralChange[i] = new fillElements(arrDataNew[i].formName, arrDataNew[i].name, arrDataNew[i].callout);
      }
    }
    if (formElementEvent(obj, name, callout)) return true;
  }
  /*try {
    document.focus();
  } catch (e) {}*/
  return true;
}

function inputValueForms(name, campo) {
  var result = "";
  if (campo==null || !campo) return "";
  if (!campo.type && campo.length>1) campo = campo[0];
  if (campo.type) {
    if (campo.type.toUpperCase().indexOf("SELECT")!=-1) {
      if (campo.selectedIndex==-1) return "";
      else {
        var length = campo.options.length;
        for (var fieldsCount=0;fieldsCount<length;fieldsCount++) {
          if (campo.options[fieldsCount].selected) {
            if (result!="") result += "&";
            result += name + "=" + escape(campo.options[fieldsCount].value);
          }
        }
        return result;
      }
    } else if (campo.type.toUpperCase().indexOf("RADIO")!=-1 || campo.type.toUpperCase().indexOf("CHECK")!=-1) {
      if (!campo.length) {
        if (campo.checked) return (name + "=" + escape(campo.value));
        else return "";
      } else {
        var total = campo.length;
        for (var i=0;i<total;i++) {
          if (campo[i].checked) {
            if (result!="") result += "&";
            result += name + "=" + escape(campo[i].value);
          }
        }
        return result;
      }
    } else return name + "=" + escape(campo.value);
  }

  return "";
}

function setFocus(campo) {
  if (campo==null || !campo) return "";
  if (!campo.type && campo.length>1) campo = campo[0];
  try {
    campo.focus();
  } catch (ignored) {}

  return "";
}

/**
* @name inputValue
* @format function inputValue(campo)
* @comment Obtiene el valor de un campo. Se encarga de toda la lógica para controlar si el campo 
*          existe, o si es un array de campos o un campo simple...
*
* @param <b>campo</b> - Es un objeto que referencia al campo del que se quiere obtener el valor.
*
* @return Devuelve un valor en blanco si no existe el campo o el valor del campo.
* @example inputValue(document.frmMain.inpInput);
*/
function inputValue(campo) {
  if (campo==null || !campo) return "";
  if (!campo.type && campo.length>1) campo = campo[0];
  if (campo.type) {
    if (campo.type.toUpperCase().indexOf("SELECT")!=-1) {
      if (campo.selectedIndex==-1) return "";
      else return campo.options[campo.selectedIndex].value;
    } else if (campo.type.toUpperCase().indexOf("RADIO")!=-1 || campo.type.toUpperCase().indexOf("CHECK")!=-1) {
      if (!campo.length)
      return ((campo.checked)?campo.value:"N");
      var total = campo.length;
      for (var i=0;i<total;i++) {
        if (campo[i].checked) return campo[i].value;
      }
      return "N";
    } else return campo.value;
  }

  return "";
}

function setInputValue(campo, myvalue) {
  if (campo==null || campo=="") return false;
  var obj = document.forms[0].elements[campo];
  if (obj==null) return false;
  if (obj.length>1) {
    var total = obj.length;
    for (var i=0;i<total;i++) obj[i].value = myvalue;
  } else obj.value = myvalue;
  return true;
}

/**
* @name displayLogicElement
* @format function displayLogicElement(id, display)
* @comment Es la función que presenta u oculta elementos de la página, es decir, es la que
*          implementa el display logic de la ventana.
*
* @param <b>id</b> - Es el id del objeto que queremos ocultar o presentar.<BR>
*        <b>display</b> - Booleano que nos indica si tenemos que ocultarlo o presentarlo.
*
* @return Devuelve <b>true</b> si se procesa correctamente o <b>false</b> en caso contrario.
* @example displayLogicElement('buttonField', true);
*/
function displayLogicElement(id, display) {
  var obj = getStyle(id);
  if (obj==null) return false;
  if (id.indexOf("_td")!=-1) {
    obj = getReference(id);
    if (display) obj.className = obj.className.replace("_Nothing","");
    else {
      obj.className = obj.className.replace("_Nothing","");
      obj.className = obj.className + "_Nothing";
    }
  } else {
    if (display) obj.display="";
    else obj.display="none";
  }
  return true;
}

/**
* @name estaEnCombo
* @format function estaEnCombo(combo, clave)
* @comment Busca una clave entre los elementos de un combo. Es una función de utilidad, es decir, es 
*          utilizada por otras funciones para realizar sus operaciones.
*
* @param <b>combo</b> - Es un objeto que referencia al combo en el que queremos buscar.<BR>
*        <b>clave</b> - Es la clave que queremos buscar en el combo.
*
* @return Devuelve un booleano que será <b>true</b> si la encuentra en el combo o <b>false</b>.
* @example estaEnCombo(documento.frmMain, '12');
*/
function estaEnCombo(combo, clave) {
  if (combo==null || clave==null) return false;
  var total = combo.options.length;
  for (var i=0;i<total;i++) {
    if (combo.options[i].value == clave) return true;
  }
  return false;
}

/**
* @name auto_completar_numero
* @format function auto_completar_numero(campo, decimal, negativo)
* @comment Es una función de control de evento de pulsación de teclado que nos permite 
*          controlar si se trata de una pulsación numérica permitida o no. Se colocará 
*          en el evento onKeyDown u onKeyUp del campo sobre el que queremos controlar 
*          que sólo se introduzcan números.
*
* @param <b>campo</b> - Es el campo sobre el que queremos controlar la introducción de números. 
*         Lo normal es que utilicemos el objeto this.<BR>
*        <b>decimal</b> - Booleano que indica si queremos que se admitan decimales para el número.<BR>
*        <b>negativo</b> - Booleano que indica si admitimos números negativos. 
*
* @example onKeyUp="auto_completar_numero(this, true, true);return true;"
*/
function auto_completar_numero(obj, bolDecimal, bolNegativo, evt) {
  var numero;
  if (document.all) evt = window.event;
  if (document.layers) { numero = evt.which; }
  if (document.all)    { numero = evt.keyCode;}
  if (numero != obtenerCodigoTecla("ENTER") && numero != obtenerCodigoTecla("LEFTARROW") && numero != obtenerCodigoTecla("RIGHTARROW") && numero != obtenerCodigoTecla("UPARROW") && numero != obtenerCodigoTecla("DOWNARROW") && numero != obtenerCodigoTecla("DELETE") && numero != obtenerCodigoTecla("BACKSPACE") && numero != obtenerCodigoTecla("END") && numero != obtenerCodigoTecla("HOME") && !evt["ctrlKey"]) {
    if (numero>95 && numero <106) { //Teclado numérico
      numero = numero - 96;
      if(isNaN(numero)) {
        if (document.all) evt.returnValue = false;
        return false;
      }
    } else if (numero!=obtenerCodigoTecla("DECIMAL") && numero != obtenerCodigoTecla("NUMBERDECIMAL") && numero != obtenerCodigoTecla("NEGATIVE") && numero != obtenerCodigoTecla("NUMBERNEGATIVE")) { //No es "-" ni "."
      numero = String.fromCharCode(numero);
      if(isNaN(numero)) {
        if (document.all) evt.returnValue = false;
        return false;
      }
    } else if (numero==obtenerCodigoTecla("DECIMAL") || numero==obtenerCodigoTecla("NUMBERDECIMAL")) { //Es "."
      if (bolDecimal) {
        if (obj.value==null || obj.value=="") return true;
        else {
          var point = obj.value.indexOf(".");
          if (point != -1) {
            point = obj.value.indexOf(".", point+1);
            if (point==-1) return true;
          } else return true;
        }
      }
      if (document.all) evt.returnValue = false;
      return false;
    } else { //Es "-"
      if (bolNegativo && (obj.value==null || obj.value.indexOf("-")==-1)) return true;
      if (document.all) evt.returnValue = false;
      return false;
    }
  }
  return true;
}

/**
* @name logChanges
* @format function logChanges(campo)
* @comment Se trata de un log para controlar si se han producido cambios en una ventana. Se 
*          pone en el evento onChange de los campos a registrar y, requiere que exista, en 
*          la propia ventana, un campo llamado inpLastFieldChanged.<BR>
*          Utiliza la función setChangedField para realizar el log.
*
* @param <b>campo</b> - Es el campo de la ventana sobre el que queremos registrar si se han 
*         producido cambios. Normalmente se colocará esta función en el evento onChange del 
*         propio campo, por lo que utilizaremos el objeto this en este parámetro.
*
* @return Devuelve <b>true</b> si se ha procesado correctamente o <b>false</b> si el campo no 
*         existe o se produce algún error.
* @example onChange="logChanges(this);return true;"
*/
function logChanges(campo) {
  if (campo==null || !campo) return false;
  return setChangedField(campo, campo.form);
}

/**
* @name processingPopUp
* @format function processingPopUp()
* @comment Se trata de una función que se encarga de la presentación de un popUp con un texto 
*          de procesando y una barra de progreso en movimiento, pero que sólo serviría para 
*          presentarlo mientras se está ejecutando una llamada larga y se debería cerrar después.
*
* @return Devuelve un objeto que permite manejar la ventana.
*/
function processingPopUp() {
  var complementosNS4 = ""

  var strHeight=100, strWidth=200;
  var strTop=parseInt((screen.height - strHeight)/2);
  var strLeft=parseInt((screen.width - strWidth)/2);
  
  if (navigator.appName.indexOf("Netscape"))
    complementosNS4 = "alwaysRaised=1, dependent=1, directories=0, hotkeys=0, menubar=0, ";
  var complementos = complementosNS4 + "height=" + strHeight + ", width=" + strWidth + ", left=" + strLeft + ", top=" + strTop + ", screenX=" + strLeft + ", screenY=" + strTop + ", location=0, resizable=0, status=0, toolbar=0, titlebar=0";
  var winPopUp = window.open("", "_blank", complementos);
  if (winPopUp!=null) {
    document.onunload = function(){winPopUp.close();};
    document.onmousedown = function(){winPopUp.close();};
    winPopUp.document.writeln("<html>\n");
    winPopUp.document.writeln("<head>\n");
    winPopUp.document.writeln("<title>Proceso petici&oacute;n</title>\n");
    winPopUp.document.writeln("<script language=\"javascript\" type=\"text/javascript\">\n");
    winPopUp.document.writeln("function selectTD(name, seleccionar) {\n");
    winPopUp.document.writeln("  var obj = getStyle(name);\n");
    winPopUp.document.writeln("  if (document.layers) {\n");
    winPopUp.document.writeln("    if (seleccionar) obj.bgColor=\"" + gColorSelected + "\";\n");
    winPopUp.document.writeln("    else obj.bgColor=\"" + gWhiteColor + "\";\n");
    winPopUp.document.writeln("  } else {\n");
    winPopUp.document.writeln("    if (seleccionar) obj.backgroundColor = \"" + gColorSelected + "\";\n");
    winPopUp.document.writeln("    else obj.backgroundColor=\"" + gWhiteColor + "\";\n");
    winPopUp.document.writeln("  }\n");
    winPopUp.document.writeln("  return seleccionar;\n");
    winPopUp.document.writeln("}\n");
    winPopUp.document.writeln("function getReference(id) {\n");
    winPopUp.document.writeln("  if (document.getElementById) return document.getElementById(id);\n");
    winPopUp.document.writeln("  else if (document.all) return document.all[id];\n");
    winPopUp.document.writeln("  else if (document.layers) return document.layers[id];\n");
    winPopUp.document.writeln("  else return null;\n");
    winPopUp.document.writeln("}\n");
    winPopUp.document.writeln("function getStyle(id) {\n");
    winPopUp.document.writeln("  var ref = getReference(id);\n");
    winPopUp.document.writeln("  if (ref==null || !ref) return null;\n");
    winPopUp.document.writeln("  return ((document.layers) ? ref : ref.style);\n");
    winPopUp.document.writeln("}\n");
    winPopUp.document.writeln("var total=5;\n");
    winPopUp.document.writeln("function loading(num) {\n");
    winPopUp.document.writeln(" if (num>=total) {\n");
    winPopUp.document.writeln("   for (var i=0;i<total;i++) {\n");
    winPopUp.document.writeln("     selectTD(\"TD\" + i, false);\n");
    winPopUp.document.writeln("   }\n");
    winPopUp.document.writeln("   num=-1;\n");
    winPopUp.document.writeln(" } else {\n");
    winPopUp.document.writeln("   selectTD(\"TD\" + num, true);\n");
    winPopUp.document.writeln(" }\n");
    winPopUp.document.writeln(" setTimeout('loading(' + (++num) + ')', 1000);\n");
    winPopUp.document.writeln(" return true;\n");
    winPopUp.document.writeln("}\n");
    winPopUp.document.writeln("</script>\n");
    winPopUp.document.writeln("</head>\n");
    winPopUp.document.writeln("<body leftmargin=\"0\" topmargin=\"0\" marginwidth=\"0\" marginheight=\"0\" onLoad=\"loading(0);\">\n");
    winPopUp.document.writeln("  <table width=\"80%\" border=\"0\" cellspacing=\"3\" cellpadding=\"0\" align=\"center\">\n");
    winPopUp.document.writeln("    <tr>\n");
    winPopUp.document.writeln("      <td colspan=\"5\" align=\"center\"><font color=\"navy\" size=\"5\">PROCESSING...</font></td>\n");
    winPopUp.document.writeln("    </tr>\n");
    winPopUp.document.writeln("    <tr bgcolor=\"" + gWhiteColor + "\">\n");
    winPopUp.document.writeln("      <td width= \"20%\" id=\"TD0\" bgcolor=\"" + gWhiteColor + "\">&nbsp;</td>\n");
    winPopUp.document.writeln("      <td width=\"20%\" id=\"TD1\" bgcolor=\"" + gWhiteColor + "\">&nbsp;</td>\n");
    winPopUp.document.writeln("      <td width=\"20%\" id=\"TD2\" bgcolor=\"" + gWhiteColor + "\">&nbsp;</td>\n");
    winPopUp.document.writeln("      <td width=\"20%\" id=\"TD3\" bgcolor=\"" + gWhiteColor + "\">&nbsp;</td>\n");
    winPopUp.document.writeln("      <td width=\"20%\" id=\"TD4\" bgcolor=\"" + gWhiteColor + "\">&nbsp;</td>\n");
    winPopUp.document.writeln("    </tr>\n");
    winPopUp.document.writeln("  </table>\n");
    winPopUp.document.writeln("</body>\n");
    winPopUp.document.writeln("</html>\n");
    winPopUp.document.close();
    winPopUp.focus();
  }
  return winPopUp;
}

/**
* @name round
* @format function round(nummero, decimales)
* @comment Realiza el redondeo de un valor numérico al número de decimales indicado
*
* @param <b>numero</b> - Es el número que queremos redondear.<BR>
*        <b>decimales</b> - Es el número de decimales al que queremos redondear el número.
*
* @return Devuelve el número redondeado o 0 si no es un número válido.
* @example round(12.234, 2);
*/
function round(number,X) {
  X = (!X ? 2 : X);
  if (!number || isNaN(number)) return 0;
  return Math.round(number*Math.pow(10,X))/Math.pow(10,X);
}

function ReplaceText(texto, replaceWhat, replaceWith) {
  if (texto==null || texto.length==0) return "";
  texto += "";
  var i = texto.indexOf(replaceWhat);
  var j = 0;
  while (i!=-1) {
    var partial = texto.substring(0, i);
    texto = texto.substring(i+replaceWhat.length);
    texto = partial + replaceWith + texto;
    j = i + replaceWith.length;
    i = texto.indexOf(replaceWhat, j);
  }
  return texto;
}

function updateOnChange(field) {
  if (field==null) return false;
  try {
    var lastChanged = inputValue(document.forms[0].inpLastFieldChanged);
    if (field.name!="inpadClientId" && field.name!="inpadOrgId") field.onchange();
    setInputValue(document.forms[0].inpLastFieldChanged, lastChanged);
  } catch (e) {}
  return true;
}

/**
* @name xx
* @format function xx()
* @comment Esta función no hace nada, simplemente sirve para ponerla en el diseño para ser sustituida, 
*          pero hacer que el diseño siga funcionando
*/
function xx()
{
  return true;
}

/**
* @name menuContextual
* @format function menuContextual()
* @comment Se trata de un función manejadora de eventos que sirve para el control del click con el 
*          botón derecho sobre la página. Esta función no permite dicho evento, presentando un mensaje 
*          en tal caso.
*/
function menuContextual(evt) {
  var boton = (evt==null)?event.button:evt.which;
  if (boton == 3 || boton == 2) {
    if (document.all) alert('El boton derecho está deshabilitado por pruebas');
    return false;
  }
  return true;
}

/*
COMPATIBILIDAD DEL CALENDARIO CON ELEMENTOS EXTERNOS
*/
// This function gets called when the end-user clicks on some date.
function selected(cal, date) {
  cal.sel.value = date; // just update the date in the input field.
  if (cal.dateClicked && (cal.sel.id == "sel1" || cal.sel.id == "sel3"))
    // if we add this call we close the calendar on single-click.
    // just to exemplify both cases, we are using this only for the 1st
    // and the 3rd field, while 2nd and 4th will still require double-click.
    cal.callCloseHandler();
}

// And this gets called when the end-user clicks on the _selected_ date,
// or clicks on the "Close" button.  It just hides the calendar without
// destroying it.
function closeHandler(cal) {
  cal.hide();                        // hide the calendar
//  cal.destroy();
  _dynarch_popupCalendar = null;
}

function getDateFormat(str_format) {
  var format = "";
  if (str_format!=null && str_format!="" && (str_format.substring(0,1) == "M" || str_format.substring(0,1) == "m")) {
    format = "%m-%d-%Y";
  } else if (str_format!=null && str_format!="" && (str_format.substring(0,1) == "D" || str_format.substring(0,1) == "d")) {
    format = "%d-%m-%Y";
  }
  if (str_format==null || str_format=="") str_format = defaultDateFormat;
  else if (str_format.indexOf(" %H:%M:%S")!=-1) format += " %H:%M:%S";
  else if (str_format.indexOf(" %H:%M")!=-1) format += " %H:%M";
  return format;
}

function showCalendar(id, value, debug, format, showsTime, showsOtherMonths) {
  //var el = document.getElementById(id);
  var el = eval("document." + id);
  if (showsTime==null) showsTime = "";
  if (showsOtherMonths==null) showsOtherMonths = false;
  if (format==null || format=="") format = getDateFormat(el.getAttribute("displayformat"));
  else format = getDateFormat(format);
  if (format.indexOf(" %H:%M")!=-1) showsTime = "24";
  
  if (_dynarch_popupCalendar != null) {
    // we already have some calendar created
    _dynarch_popupCalendar.hide();                 // so we hide it first.
  } else {
    // first-time call, create the calendar.
    var cal = new Calendar(1, null, selected, closeHandler);
    // uncomment the following line to hide the week numbers
    cal.weekNumbers = false;
    if (typeof showsTime == "string" && showsTime!="") {
      cal.showsTime = true;
      cal.time24 = (showsTime == "24");
    }
    if (showsOtherMonths) {
      cal.showsOtherMonths = true;
    }
    _dynarch_popupCalendar = cal;                  // remember it in the global var
    cal.setRange(1900, 2070);        // min/max year allowed.
    cal.create();
  }
  dateFormat = format;
  _dynarch_popupCalendar.setDateFormat(format);    // set the specified date format
  _dynarch_popupCalendar.parseDate(el.value);      // try to parse the text in field
  _dynarch_popupCalendar.sel = el;                 // inform it what input field we use

  // the reference element that we pass to showAtElement is the button that
  // triggers the calendar.  In this example we align the calendar bottom-right
  // to the button.
  _dynarch_popupCalendar.showAtElement(el, "Br");        // show the calendar

  return false;
}

function datecmp(date1, date2, fmt) {
  if (date1==null || date1 == "") return null;
  else if (date2==null || date2 == "") return null;
  fmt = getDateFormat(fmt);
  var mydate1 = Date.parseDate(date1, fmt);
  var mydate2 = Date.parseDate(date2, fmt);
  if (mydate1==null || mydate1=="" || mydate2==null || mydate2=="") return null;
  if (mydate1.getFullYear() > mydate2.getFullYear()) return 1;
  else if (mydate1.getFullYear() == mydate2.getFullYear()) {
    if (mydate1.getMonth() > mydate2.getMonth()) return 1;
    else if (mydate1.getMonth() == mydate2.getMonth()) {
      if (mydate1.getDate() > mydate2.getDate()) return 1;
      else if (mydate1.getDate() == mydate2.getDate()) {
        if (mydate1.getHours() > mydate2.getHours()) return 1;
        else if (mydate1.getHours() == mydate2.getHours()) {
          if (mydate1.getMinutes() > mydate2.getMinutes()) return 1;
          else if (mydate1.getMinutes() == mydate2.getMinutes()) return 0;
          else return -1;
        } else return -1;
      } else return -1;
    } else return -1;
  } else return -1;
}

function checkFormat(formatType) {
  switch (formatType) {
    case 'Y': return 4;
    case 'm': return 2;
    case 'd': return 2;
    default: return 2;
  }
  return 0;
}

function getSeparators(format) {
  if (format==null || format.length==0) return null;
  var result = new Array();
  var pos = format.indexOf("%");
  var last = 0;
  var i=0;
  while (pos!=-1) {
    if (pos>last) {
      result[i++] = format.substring(last, pos);
    }
    last = pos+2;
    pos = format.indexOf("%", last);
  }
  if (last < format.length) result[i] = format.substring(last);
  return result;
}

function isInArray(obj, text) {
  if (obj==null || obj.length==0) return false;
  if (text==null || text.length==0) return false;
  var total = obj.length;
  for (var i = 0;i<total;i++) {
    if (obj[i].toUpperCase()==text.toUpperCase()) return true;
  }
  return false;
}

function about() {
  var complementosNS4 = ""

  var strHeight=500;
  var strWidth=600;
  var strTop=parseInt((screen.height - strHeight)/2);
  var strLeft=parseInt((screen.width - strWidth)/2);
  if (navigator.appName.indexOf("Netscape"))
    complementosNS4 = "alwaysRaised=1, dependent=1, directories=0, hotkeys=0, menubar=0, ";
  var complementos = complementosNS4 + "height=" + strHeight + ", width=" + strWidth + ", left=" + strLeft + ", top=" + strTop + ", screenX=" + strLeft + ", screenY=" + strTop + ", location=0, resizable=yes, scrollbars=yes, status=0, toolbar=0, titlebar=0";
  var winPopUp = window.open(baseDirection + "../ad_forms/about.html", "ABOUT", complementos);
  if (winPopUp!=null) {
    winPopUp.focus();
    document.onunload = function(){winPopUp.close();};
    document.onmousedown = function(){winPopUp.close();};
  }
  return winPopUp;
}

function resizeArea(isOnResize) {
  if (isOnResize==null) isOnResize = false;
  var mnu = document.getElementById("client");
  var mleft = document.getElementById("tdLeftTabsBars");
  var mleftSeparator = document.getElementById("tdleftSeparator");
  var mright = document.getElementById("tdrightSeparator");
  var mtop = document.getElementById("tdtopNavButtons");
  var mtopToolbar = document.getElementById("tdToolBar");
  var mtopTabs = document.getElementById("tdtopTabs");
  var mbottombut = document.getElementById("tdbottomButtons");
  var mbottom = document.getElementById("tdbottomSeparator");
  var body = document.getElementsByTagName("BODY");
  var h = body[0].clientHeight;
  var w = body[0].clientWidth;
  var name = window.navigator.appName;
  mnu.style.width = w - ((mleft?mleft.clientWidth:0) + (mleftSeparator?mleftSeparator.clientWidth:0) + (mright?mright.clientWidth:0)) - ((name.indexOf("Microsoft")==-1)?2:0);
  mnu.style.height = h -((mtop?mtop.clientHeight:0) + (mtopToolbar?mtopToolbar.clientHeight:0) + (mtopTabs?mtopTabs.clientHeight:0) + (mbottom?mbottom.clientHeight:0) + (mbottombut?mbottombut.clientHeight:0)) - ((name.indexOf("Microsoft")==-1)?1:0);
/*  try {
    dojo.addOnLoad(dojo.widget.byId('grid').onResize);
  } catch (e) {}*/
  try {
    if (isOnResize) dojo.widget.byId('grid').onResize();
  } catch (e) {}
  mnu.style.display = "";
}

function resizeAreaHelp() {
  var mnu = document.getElementById("client");
  var mnuIndex = document.getElementById("clientIndex");
  var mTopSeparator = document.getElementById("tdSeparator");
  var mTopNavigation = document.getElementById("tdNavigation");
  var body = document.getElementsByTagName("BODY");
  var h = body[0].clientHeight;
  var w = body[0].clientWidth;
  var name = window.navigator.appName;
//  mnu.style.width = w - 18 - ((name.indexOf("Microsoft")==-1)?2:0);
  mnu.style.height = h -(mTopSeparator.clientHeight + mTopNavigation.clientHeight) - 2;
  mnuIndex.style.height = mnu.style.height;

  mnu.style.display = "";
  mnuIndex.style.display = "";
}

function resizeAreaUserOps() {
  var mnu = document.getElementById("client");
  var mnuIndex = document.getElementById("clientIndex");
  var mTopSeparator = document.getElementById("tdSeparator");
  var mVerSeparator = document.getElementById("tdVerSeparator");
  var mTopNavigation = document.getElementById("tdNavigation");
  var body = document.getElementsByTagName("BODY");
  var h = body[0].clientHeight;
  var w = body[0].clientWidth;
  var name = window.navigator.appName;
//  mnu.style.width = w - 18 - ((name.indexOf("Microsoft")==-1)?2:0);
  mnu.style.height = h -(mTopSeparator.clientHeight + mTopNavigation.clientHeight) - 2;
  mnuIndex.style.height = mnu.style.height;

  mnuIndex.style.display = "";

  mnu.style.width= w - (mVerSeparator.clientWidth + mnuIndex.clientWidth) - 2;

  mnu.style.display = "";
}

/*if (!document.all)
  document.captureEvents(Event.MOUSEDOWN);
document.onmousedown=menuContextual;*/

//-->
